2020-08-12 15:15:31 +02:00
|
|
|
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';
|
2020-08-20 10:42:02 +02:00
|
|
|
import cloneDeep from 'lodash/cloneDeep';
|
2020-08-28 08:14:57 +02:00
|
|
|
import omit from 'lodash/omit';
|
2020-08-20 10:42:02 +02:00
|
|
|
import {DataService} from '../services/data.service';
|
|
|
|
import {ModelItemModel} from '../models/model-item.model';
|
|
|
|
|
2020-08-12 15:15:31 +02:00
|
|
|
|
|
|
|
@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 {
|
|
|
|
|
2020-10-02 10:11:16 +02:00
|
|
|
result: {predictions: any[], mean: any[]}; // prediction result from python container
|
2020-08-12 15:15:31 +02:00
|
|
|
loading = false;
|
2020-08-20 10:42:02 +02:00
|
|
|
activeGroup: ModelItemModel = new ModelItemModel();
|
|
|
|
activeModelIndex = 0;
|
2020-09-03 15:51:53 +02:00
|
|
|
// if true, spectra belong to different samples, otherwise multiple spectra from the same sample are given
|
|
|
|
multipleSamples = false;
|
2020-08-20 10:42:02 +02:00
|
|
|
spectrumNames: string[] = [];
|
2020-08-12 15:15:31 +02:00
|
|
|
spectrum: string[][] = [[]];
|
2020-08-20 10:42:02 +02:00
|
|
|
flattenedSpectra = [];
|
|
|
|
chart = [];
|
|
|
|
readonly chartInit = {
|
2020-08-12 15:15:31 +02:00
|
|
|
data: [],
|
|
|
|
label: 'Spectrum',
|
|
|
|
showLine: true,
|
|
|
|
fill: false,
|
|
|
|
pointRadius: 0,
|
|
|
|
borderColor: '#00a8b0',
|
|
|
|
borderWidth: 2
|
2020-08-20 10:42:02 +02:00
|
|
|
};
|
2020-08-12 15:15:31 +02:00
|
|
|
readonly chartOptions: ChartOptions = {
|
|
|
|
scales: {
|
|
|
|
xAxes: [{ticks: {min: 400, max: 4000, stepSize: 400, reverse: true}}],
|
2020-09-03 15:51:53 +02:00
|
|
|
yAxes: [{ticks: {}}]
|
2020-08-12 15:15:31 +02:00
|
|
|
},
|
|
|
|
responsive: true,
|
|
|
|
tooltips: {enabled: false},
|
|
|
|
hover: {mode: null},
|
|
|
|
maintainAspectRatio: true,
|
|
|
|
plugins: {datalabels: {display: false}}
|
|
|
|
};
|
|
|
|
|
|
|
|
constructor(
|
2020-08-20 10:42:02 +02:00
|
|
|
private api: ApiService,
|
|
|
|
public d: DataService
|
|
|
|
) {
|
|
|
|
this.chart[0] = cloneDeep(this.chartInit);
|
|
|
|
}
|
2020-08-12 15:15:31 +02:00
|
|
|
|
|
|
|
ngOnInit(): void {
|
2020-08-20 10:42:02 +02:00
|
|
|
this.d.load('modelGroups', () => {
|
|
|
|
this.activeGroup = this.d.arr.modelGroups[0];
|
|
|
|
});
|
2020-08-12 15:15:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fileToArray(files) {
|
2020-08-20 10:42:02 +02:00
|
|
|
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 = () => {
|
2020-09-03 15:51:53 +02:00
|
|
|
// parse to database spectrum representation
|
2020-08-26 19:25:31 +02:00
|
|
|
this.spectrum = fileReader.result.toString().split('\r\n').map(e => e.split(',').map(el => parseFloat(el)))
|
|
|
|
.filter(el => el.length === 2) as any;
|
2020-09-03 15:51:53 +02:00
|
|
|
// flatten to format needed for prediction
|
2020-08-20 10:42:02 +02:00
|
|
|
this.flattenedSpectra[i] = {labels: this.spectrum.map(e => e[0]), values: this.spectrum.map(e => e[1])};
|
2020-09-03 15:51:53 +02:00
|
|
|
// add to chart
|
2020-08-20 10:42:02 +02:00
|
|
|
this.chart[i] = cloneDeep(this.chartInit);
|
|
|
|
this.chart[i].data = this.spectrum.map(e => ({x: parseFloat(e[0]), y: parseFloat(e[1])}));
|
|
|
|
load --;
|
2020-09-03 15:51:53 +02:00
|
|
|
if (load <= 0) { // all loaded
|
2020-08-20 10:42:02 +02:00
|
|
|
this.loadPrediction();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
fileReader.readAsText(files[i]);
|
|
|
|
}
|
|
|
|
}
|
2020-08-12 15:15:31 +02:00
|
|
|
}
|
|
|
|
|
2020-08-20 10:42:02 +02:00
|
|
|
loadPrediction() {
|
|
|
|
this.loading = true;
|
2020-08-28 08:14:57 +02:00
|
|
|
this.api.post<any>(this.activeGroup.models[this.activeModelIndex].url, this.flattenedSpectra, data => {
|
2020-10-02 10:11:16 +02:00
|
|
|
let tmp = Object.entries(omit(data, ['mean', 'std', 'label'])) // form: [[label, [{value, color}]]]
|
|
|
|
.map((entry: any) => entry[1].map(e => ({category: entry[0], label: data.label[entry[0]], value: e.value, color: e.color}))); // form: [[{category, label, value, color}]]
|
|
|
|
this.result = {
|
|
|
|
predictions: tmp[0].map((ignore, columnIndex) => tmp.map(row => row[columnIndex])), // transpose tmp
|
|
|
|
mean: Object.entries(data.mean)
|
|
|
|
.map((entry:any) => ({category: entry[0], label: data.label[entry[0]], value: entry[1].value, color: entry[1].color, std: data.std[entry[0]]})) // form: [{category, label, value, color}]
|
2020-08-28 08:14:57 +02:00
|
|
|
};
|
2020-08-20 10:42:02 +02:00
|
|
|
this.loading = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-09-03 15:51:53 +02:00
|
|
|
groupChange(index) { // group was changed
|
2020-08-20 10:42:02 +02:00
|
|
|
this.activeGroup = this.d.arr.modelGroups[index];
|
2020-08-31 16:14:47 +02:00
|
|
|
this.activeModelIndex = 0;
|
2020-08-20 10:42:02 +02:00
|
|
|
this.result = undefined;
|
|
|
|
}
|
2020-08-28 08:14:57 +02:00
|
|
|
|
|
|
|
clip(str) { // clip spaces at start and end
|
|
|
|
return str.replace(/^\s*(.*?)\s*$/, '$1');
|
|
|
|
}
|
2020-08-12 15:15:31 +02:00
|
|
|
}
|