Commit eb98d613 authored by Kruyff,D.L.W. (Dylan)'s avatar Kruyff,D.L.W. (Dylan)
Browse files

Replaced http server with angular app + naive labeling

parent 34732969
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { SettingsComponent } from './settings/settings.component';
import { OverviewWindowComponent } from './overview-window/overview-window.component';
import * as PlotlyJS from 'plotly.js/dist/plotly.js';
import { PlotlyModule } from 'angular-plotly.js';
import {FormsModule} from '@angular/forms';
import { LabelingWindowComponent } from './labeling-window/labeling-window.component';
PlotlyModule.plotlyjs = PlotlyJS;
@NgModule({
declarations: [
AppComponent,
SettingsComponent,
OverviewWindowComponent,
LabelingWindowComponent,
],
imports: [
BrowserModule,
FormsModule,
PlotlyModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
import {EventEmitter, Injectable} from '@angular/core';
import {ApiService, RawData} from './api.service';
@Injectable({
providedIn: 'root'
})
export class CacheService {
public rawValues: number[];
public rawIndices: string[];
public windows: number[][];
public hashFunctions;
public tables;
public windowSimilarity;
public windowSize = 20;
public nrOfTables = 10;
public hashSize = 10;
public onQuery: EventEmitter<void> = new EventEmitter<void>();
public onNewTables: EventEmitter<void> = new EventEmitter<void>();
public onNewWindows: EventEmitter<void> = new EventEmitter<void>();
public initialized: Promise<void>;
constructor(private api: ApiService) {
this.initialized = this.initialize();
}
async initialize(): Promise<void> {
await this.getRawData();
await this.getWindows();
await this.createTables();
}
async reset(): Promise<void> {
this.windowSimilarity = undefined;
await this.getWindows();
await this.createTables();
}
async getRawData(): Promise<void> {
const rawData: RawData = await this.api.readFile();
this.rawIndices = rawData.index;
this.rawValues = rawData.values;
}
async getWindows(): Promise<void> {
this.windows = await this.api.createWindows(this.rawValues, this.parameters);
this.onNewWindows.emit();
}
async createTables(): Promise<void> {
this.tables = await this.api.createTables(this.windows, this.parameters);
this.onNewTables.emit();
}
async getSimilarWindows(window): Promise<any> {
this.windowSimilarity = await this.api.getSimilarWindows(window, this.tables);
this.onQuery.emit();
return this.windowSimilarity;
}
async updateTables(labeldata): Promise<void> {
this.tables = await this.api.updateTables(this.windows, labeldata, this.tables, this.parameters);
this.onNewTables.emit();
}
public get parameters(): {[parameter: string]: any} {
return {
windowsize: this.windowSize,
hashsize: this.hashSize,
tablesize: this.nrOfTables
};
}
}
.subplot {
margin-right: 20px;
}
button {
color: white;
}
.button-holder {
display: flex;
}
.correct-selected { background-color: #4CAF50 }
.neutral-selected { background-color: #008CBA }
.incorrect-selected { background-color: #f44336 }
<div *ngIf="windowSimilarity" style="display: flex;">
<div class="subplot" *ngFor="let subplot of subplots">
<plotly-plot [data]="subplot.data" [layout]="subplot.layout"></plotly-plot>
<div class="button-holder">
<button class="correct-button" [class.correct-selected]="labels[subplot.index]" (click)="labelCorrect(subplot.index)">Correct</button>
<button class="neutral-button" [class.neutral-selected]="labels[subplot.index] == undefined" (click)="labelUndefined(subplot.index)">Neutral</button>
<button class="incorrect-button" [class.incorrect-selected]="labels[subplot.index] == false" (click)="labelIncorrect(subplot.index)">Incorrect</button>
</div>
</div>
</div>
<button (click)="changeTables()">Label data</button>
import { Component, OnInit } from '@angular/core';
import {CacheService} from '../cache.service';
@Component({
selector: 'app-labeling-window',
templateUrl: './labeling-window.component.html',
styleUrls: ['./labeling-window.component.css']
})
export class LabelingWindowComponent implements OnInit {
public topk;
public subplots = [];
public labels: boolean[] = [];
private k = 5;
constructor(private service: CacheService) { }
ngOnInit(): void {
this.service.onQuery.subscribe(() => { this.getTopKSimilar(); });
}
public changeTables() {
console.log(this.labels);
this.service.updateTables(this.labels);
}
public get windowSimilarity() {
return this.service.windowSimilarity;
}
public labelCorrect(index: number) {
this.labels[index] = true;
}
public labelUndefined(index: number) {
if (this.labels[index] !== undefined) {
delete this.labels[index];
}
}
public labelIncorrect(index: number) {
this.labels[index] = false;
}
public getTopKSimilar() {
this.labels = [];
let topk = [];
let k = this.k;
const keys = Object.keys(this.windowSimilarity).map(a => Number(a)).sort((a, b) => b - a);
for (const key of keys) {
const windows = this.windowSimilarity[key];
const nrOfWindows = windows.length;
if (nrOfWindows >= k) {
const temp = windows.slice(0, k).map((index) => ({index, frequency: 100 * key / this.service.nrOfTables}));
topk = topk.concat(temp);
break;
} else {
k -= nrOfWindows;
const temp = windows.map(index => ({index, frequency: 100 * key / this.service.nrOfTables}));
topk = topk.concat(temp);
}
}
this.topk = topk;
this.subplots = [];
for (const window of this.topk) {
this.subplots.push(
{
index: window.index,
data: [{
x: this.service.rawIndices.slice(window.index, window.index + this.service.windowSize),
y: this.service.rawValues.slice(window.index, window.index + this.service.windowSize),
type: 'line'
}],
layout: {
title: `Index: ${window.index.toString()} Similarity: ${window.frequency.toString()}%`,
hovermode: 'closest',
autosize: true,
margin: {
l: 30,
r: 30,
t: 30,
pad: 4
},
height: 200,
width: 200,
titlefont: {
size: 9
},
}
}
);
}
}
}
<plotly-plot *ngIf="showPlot" [data]="data" [layout]="layout" (plotly_click)="clicked($event)"></plotly-plot>
import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
import { CacheService } from '../cache.service';
import {throwError} from 'rxjs';
@Component({
selector: 'app-overview-window',
templateUrl: './overview-window.component.html',
styleUrls: ['./overview-window.component.css']
})
export class OverviewWindowComponent implements OnInit {
public defaultColors: string[] = [];
public defaultSizes: number[] = [];
public defaultOpacity: number[] = [];
public selectedIndex: number;
public showPlot = false;
public data;
public layout;
constructor(private service: CacheService) { }
async ngOnInit(): Promise<void> {
this.service.onNewWindows.subscribe(() => { this.initializePlot(); });
this.service.onNewTables.subscribe(() => {
if (this.selectedIndex) {
this.updatePlot();
}
});
}
async initializePlot() {
this.selectedIndex = undefined;
for (const _ of this.service.rawValues) {
this.defaultColors.push('#a3a7e4');
this.defaultSizes.push(5);
this.defaultOpacity.push(1);
}
this.data = [{
x: this.service.rawIndices,
y: this.service.rawValues,
type: 'scatter',
mode: 'markers',
marker: {
size: this.defaultSizes.slice(),
color: this.defaultColors.slice()}
}];
this.layout = {
hovermode: 'closest',
autosize: true,
margin: {
l: 0,
r: 0,
b: 40,
t: 0,
pad: 4
},
height: 200
};
this.showPlot = true;
}
async clicked(clickData) {
for (const point of clickData.points) {
this.selectedIndex = point.pointNumber;
}
await this.updatePlot();
}
async updatePlot() {
const colors: string[] = [];
const sizes: number[] = [];
const opacity: number[] = [];
const windowSimilarity = await this.service.getSimilarWindows(this.service.windows[this.selectedIndex]);
for (const frequency in windowSimilarity){
for (const index of windowSimilarity[frequency]) {
colors[index] = this.getColor(Number(frequency) / this.service.nrOfTables);
sizes[index] = (Number(frequency) / this.service.nrOfTables) * 10;
opacity[index] = Number(frequency) / this.service.nrOfTables;
}
}
this.data[0].marker.color = colors;
}
public getColor(value: number) {
// value from 0 to 1
const hueValue = Math.min((1 - value) , 1);
const hue = ((1 - hueValue) * 120).toString(10);
const sat = value * 100;
return `hsl(${hue}, ${sat}%, 50%)`;
}
}
input {
width: 30px;
}
.settings-container {
}
<div class="settings-container">
<button (click)="reset()">Full Reset</button>
<button (click)="newTables()">Generate new tables</button>
<div>
<label for="windowsize">Window Size:</label><br>
<input [(ngModel)]="windowSize" id="windowsize">
</div>
<div>
<label for="hashsize">Hash Size:</label><br>
<input [(ngModel)]="hashSize" id="hashsize">
</div>
<div>
<label for="nroftables">Number of tables:</label><br>
<input [(ngModel)]="nrOfTables" id="nroftables">
</div>
</div>
import { Component, OnInit } from '@angular/core';
import {CacheService} from '../cache.service';
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.css']
})
export class SettingsComponent implements OnInit {
private _windowSize;
private _hashSize;
private _nrOfTables;
constructor(private service: CacheService) { }
ngOnInit(): void {
this._windowSize = this.service.windowSize;
this._hashSize = this.service.hashSize;
this._nrOfTables = this.service.nrOfTables;
}
public reset() {
this.service.windowSize = this._windowSize;
this.service.hashSize = this._hashSize;
this.service.nrOfTables = this._nrOfTables;
this.service.reset();
}
public newTables() {
this.service.hashSize = this._hashSize;
this.service.nrOfTables = this._nrOfTables;
this.service.createTables();
}
public get windowSize() {
return this._windowSize;
}
public set windowSize(v) {
this._windowSize = v;
}
public get hashSize() {
return this._hashSize;
}
public set hashSize(v) {
this._hashSize = v;
}
public get nrOfTables() {
return this._nrOfTables;
}
public set nrOfTables(v) {
this._nrOfTables = v;
}
}
export const environment = {
production: true
};
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Prototype</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
/* You can add global styles to this file, and also import other style files */
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment