annotate src/app/services/feature-extraction/feature-extraction.service.ts @ 424:bb2bc6af642b

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