import { Component, OnInit } from '@angular/core'; import {ChartOptions} from 'chart.js'; import {ApiService} from '../services/api.service'; import {animate, style, transition, trigger} from '@angular/animations'; import cloneDeep from 'lodash/cloneDeep'; import omit from 'lodash/omit'; import {DataService} from '../services/data.service'; import {ModelItemModel} from '../models/model-item.model'; @Component({ selector: 'app-prediction', templateUrl: './prediction.component.html', styleUrls: ['./prediction.component.scss'], animations: [ trigger( 'inOut', [ transition(':enter', [ style({height: 0, opacity: 0}), animate('0.5s ease-out', style({height: '*', opacity: 1})) ]), transition(':leave', [ style({height: '*', opacity: 1}), animate('0.5s ease-in', style({height: 0, opacity: 0})) ]) ] ) ] }) export class PredictionComponent implements OnInit { result: {predictions: string[], mean: string}; loading = false; activeGroup: ModelItemModel = new ModelItemModel(); activeModelIndex = 0; multipleSamples = false; // if true, spectra belong to different samples, otherwise multiple spectra from the same sample are given spectrumNames: string[] = []; spectrum: string[][] = [[]]; flattenedSpectra = []; chart = []; readonly chartInit = { data: [], label: 'Spectrum', showLine: true, fill: false, pointRadius: 0, borderColor: '#00a8b0', borderWidth: 2 }; readonly chartOptions: ChartOptions = { scales: { xAxes: [{ticks: {min: 400, max: 4000, stepSize: 400, reverse: true}}], yAxes: [{ticks: {min: 0, max: 1}}] }, responsive: true, tooltips: {enabled: false}, hover: {mode: null}, maintainAspectRatio: true, plugins: {datalabels: {display: false}} }; constructor( private api: ApiService, public d: DataService ) { this.chart[0] = cloneDeep(this.chartInit); } ngOnInit(): void { this.d.load('modelGroups', () => { this.activeGroup = this.d.arr.modelGroups[0]; }); } fileToArray(files) { this.loading = true; this.flattenedSpectra = []; this.chart = []; let load = files.length; this.spectrumNames = files.map(e => e.name); for (const i in files) { if (files.hasOwnProperty(i)) { const fileReader = new FileReader(); fileReader.onload = () => { this.spectrum = fileReader.result.toString().split('\r\n').map(e => e.split(',').map(el => parseFloat(el))) .filter(el => el.length === 2) as any; this.flattenedSpectra[i] = {labels: this.spectrum.map(e => e[0]), values: this.spectrum.map(e => e[1])}; this.chart[i] = cloneDeep(this.chartInit); this.chart[i].data = this.spectrum.map(e => ({x: parseFloat(e[0]), y: parseFloat(e[1])})); load --; if (load <= 0) { this.loadPrediction(); } }; fileReader.readAsText(files[i]); } } } loadPrediction() { this.loading = true; this.api.post(this.activeGroup.models[this.activeModelIndex].url, this.flattenedSpectra, data => { this.result = { predictions: Object.entries(omit(data, ['mean', 'std', 'label'])) .map((p: any) => p[1].map(e => `${p[0]}: ${e} ${data.label[p[0]]}`)) .reduce((s, e) => s.map((el, i) => this.clip(el) + ', ' + e[i])), mean: Object.keys(data.mean).map(e => this.clip(`${e}: ${data.mean[e]} ${data.label[e]}`) + (data.std[e] !== '' ? ` (standard deviation: ${data.std[e]})` : '') ).join(', ') }; console.log(this.result); this.loading = false; }); } groupChange(index) { this.activeGroup = this.d.arr.modelGroups[index]; this.result = undefined; } clip(str) { // clip spaces at start and end return str.replace(/^\s*(.*?)\s*$/, '$1'); } }