annotate src/app/services/feature-extraction/feature-extraction.service.ts @ 509:041468f553e1 tip master

Merge pull request #57 from LucasThompson/fix/session-stack-max-call-stack Fix accidental recursion in PersistentStack
author Lucas Thompson <LucasThompson@users.noreply.github.com>
date Mon, 27 Nov 2017 11:04:30 +0000
parents c39df81c4dae
children
rev   line source
dev@74 1 import {Injectable, Inject} from '@angular/core';
dev@47 2 import {
dev@226 3 ListResponse
dev@497 4 } from 'piper-js/core';
dev@64 5 import {
dev@497 6 OneShotExtractionRequest as SimpleRequest,
dev@497 7 } from 'piper-js/one-shot';
dev@236 8 import {Subject} from 'rxjs/Subject';
dev@236 9 import {Observable} from 'rxjs/Observable';
dev@324 10 import {Http} from '@angular/http';
dev@226 11 import {
dev@226 12 countingIdProvider,
dev@497 13 WebWorkerStreamingClient,
dev@497 14 RequestId
dev@497 15 } from 'piper-js/web-worker';
dev@497 16 import {collect, StreamingConfiguration} from 'piper-js/streaming';
dev@349 17 import {
dev@349 18 KnownShapedFeature,
dev@349 19 toKnownShape
dev@349 20 } from '../../visualisations/FeatureUtilities';
dev@494 21 import {NotificationService} from '../notifications/notifications.service';
dev@40 22
dev@74 23 type RepoUri = string;
dev@74 24 export interface AvailableLibraries {
dev@74 25 [libraryKey: string]: RepoUri;
dev@74 26 }
dev@74 27
dev@226 28 export interface Progress {
dev@226 29 id: RequestId;
dev@226 30 value: number; // between 0 and 100, for material-ui
dev@226 31 }
dev@226 32
dev@350 33 export interface ExtractionResult {
dev@350 34 id: RequestId;
dev@350 35 result: KnownShapedFeature;
dev@396 36 unit?: string;
dev@350 37 }
dev@350 38
dev@40 39 @Injectable()
dev@40 40 export class FeatureExtractionService {
dev@40 41
dev@40 42 private worker: Worker;
dev@350 43 private featuresExtracted: Subject<ExtractionResult>;
dev@350 44 featuresExtracted$: Observable<ExtractionResult>;
dev@74 45 private librariesUpdated: Subject<ListResponse>;
dev@74 46 librariesUpdated$: Observable<ListResponse>;
dev@226 47 private progressUpdated: Subject<Progress>;
dev@226 48 progressUpdated$: Observable<Progress>;
dev@226 49 private client: WebWorkerStreamingClient;
dev@44 50
dev@236 51 constructor(private http: Http,
dev@494 52 @Inject('PiperRepoUri') private repositoryUri: RepoUri,
dev@494 53 private notifier: NotificationService) {
dev@40 54 this.worker = new Worker('bootstrap-feature-extraction-worker.js');
dev@350 55 this.featuresExtracted = new Subject<ExtractionResult>();
dev@51 56 this.featuresExtracted$ = this.featuresExtracted.asObservable();
dev@74 57 this.librariesUpdated = new Subject<ListResponse>();
dev@74 58 this.librariesUpdated$ = this.librariesUpdated.asObservable();
dev@226 59 this.progressUpdated = new Subject<Progress>();
dev@226 60 this.progressUpdated$ = this.progressUpdated.asObservable();
dev@74 61 this.worker.addEventListener('message', (ev: MessageEvent) => {
dev@74 62 const isValidResponse = ev.data.method === 'import'
dev@226 63 && ev.data.result && ev.data.result.available ;
dev@74 64 if (isValidResponse) {
dev@226 65 (ev as Event).stopImmediatePropagation();
dev@74 66 this.librariesUpdated.next(ev.data.result);
dev@74 67 }
dev@226 68 }, true);
dev@226 69
dev@226 70 this.client = new WebWorkerStreamingClient(
dev@226 71 this.worker,
dev@226 72 countingIdProvider(0)
dev@236 73 );
dev@40 74 }
dev@40 75
dev@47 76 list(): Promise<ListResponse> {
dev@326 77 return this.client.list({});
dev@40 78 }
dev@40 79
dev@350 80 extract(analysisItemId: string,
dev@350 81 request: SimpleRequest): Promise<ExtractionResult> {
dev@305 82 let config: StreamingConfiguration;
dev@305 83 return collect(this.client.process(request), val => {
dev@305 84 if (val.configuration) {
dev@305 85 config = val.configuration;
dev@305 86 }
dev@305 87 const progress = val.progress;
dev@305 88 if (progress.totalBlockCount > 0) {
dev@305 89 this.progressUpdated.next({
dev@305 90 id: analysisItemId,
dev@305 91 value: (progress.processedBlockCount / progress.totalBlockCount) * 100
dev@305 92 });
dev@305 93 }
dev@305 94 }).then(features => {
dev@349 95 const shaped = toKnownShape({
dev@305 96 features: features,
dev@305 97 outputDescriptor: config.outputDescriptor
dev@226 98 });
dev@396 99 const result = config.outputDescriptor.configured.unit ? {
dev@396 100 id: analysisItemId,
dev@396 101 result: shaped,
dev@396 102 unit: shaped.shape === 'notes' ?
dev@396 103 'MIDI note' : config.outputDescriptor.configured.unit
dev@396 104 } : {
dev@350 105 id: analysisItemId,
dev@350 106 result: shaped
dev@350 107 };
dev@350 108 this.featuresExtracted.next(result);
dev@350 109 return result;
dev@305 110 });
dev@62 111 }
dev@62 112
dev@324 113 updateAvailableLibraries(): void {
dev@324 114 this.http.get(this.repositoryUri)
dev@324 115 .toPromise() // just turn into a promise for now to subscribe / execute
dev@324 116 .then(res => {
dev@74 117 this.worker.postMessage({
dev@74 118 method: 'addRemoteLibraries',
dev@324 119 params: res.json()
dev@349 120 });
dev@74 121 })
dev@494 122 .catch(err => this.notifier.displayError(err));
dev@74 123 }
dev@74 124
dev@74 125 load(libraryKey: string): void {
dev@74 126 this.worker.postMessage({method: 'import', params: libraryKey});
dev@74 127 }
dev@40 128 }