state.service.ts 7.35 KB
Newer Older
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
1
import {EventEmitter, Injectable} from '@angular/core';
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
2
import {ApiService, LshData, Parameters, RawData, State, StateNode, TableInfoData} from './api.service';
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
3
4
5
6

@Injectable({
  providedIn: 'root'
})
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
7
8
9
10
/**
 * This service acts as the state of the entire application. Components can subscribe to EventEmitters within this state to update their
 * contents.
 */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
11
export class StateService {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
12
13
14
  /**
   * These are all LSH specific variables. The variables can be accessed using the getters and setters
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
15
16
17
  public currStateIndex = 0;
  public maxStateIndex = 0;
  public states: {[idx: number]: StateNode} = {};
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
18
  private _rawData: RawData[];
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
19
  private _lshData: LshData;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
20
  private _queryWindow: number[][];
21
  private _weights: number[];
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
22
  private _labels = {};
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
23
  private _lshParameters: number[];
24
  private _selection: number[];
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
25
  public computedTime = 0;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
26
27
28
29
  public windowSize = 120;
  public nrOfTables = 5;
  public hashSize = 5;
  public stepSize = 200;
30
  public loadingText = '';
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
31
32
33
34
35

  /**
   * These are all GUI variables
   */
  public loadingProgress = 0;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
36
  public querySelectionMode = true;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
37
38
  private _currentTab: number;
  private _sliderValue;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
39

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
40
41
42
  /**
   * These are all EventEmitters. Subscribe to these if you want to be informed about an update in state.
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
43
44
45
  public onNewData: EventEmitter<void> = new EventEmitter<void>();
  public onNewWindows: EventEmitter<void> = new EventEmitter<void>();
  public onNewQuery: EventEmitter<void> = new EventEmitter<void>();
46
  public onNewLshData: EventEmitter<void> = new EventEmitter<void>();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
47
48
49
50

  public onNewLabels: EventEmitter<void> = new EventEmitter<void>();
  public onNewTab: EventEmitter<void> = new EventEmitter<void>();
  public onNewSlider: EventEmitter<number> = new EventEmitter<number>();
51
  public onNewSelection: EventEmitter<number[]> = new EventEmitter<number[]>();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
52
53

  constructor(private api: ApiService) {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
54
     this._selection = [0];
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
55
56
57
     this.initialize();
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
58
59
60
  /**
   * This function initializes the application. It retrieves the raw data and creates windows.
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
61
62
63
  async initialize(): Promise<void> {
    this.loadingProgress = 0;
    await this.getRawData();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
64
65
    // this.loadingProgress = 50;
    // await this.createWindows();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
66
67
68
    this.loadingProgress = 100;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
69
70
71
  /**
   * This function resets the application. It re-creates the windows
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
72
73
74
75
76
77
  async reset(): Promise<void> {
    this.loadingProgress = 50;
    await this.createWindows();
    this.loadingProgress = 100;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
78
79
80
  /**
   * This function retrieves the raw data
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
81
82
  async getRawData(): Promise<void> {
    this.rawData = await this.api.readFile();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
83
84
    console.log('Printing raw data:');
    console.log(this.rawData);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
85
86
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
87
88
89
  /**
   * This function creates the windows on the server side
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
90
91
92
93
94
  async createWindows(): Promise<void> {
    await this.api.createWindows(this.parameters);
    this.onNewWindows.emit();
  }

95
96


Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
97
98
99
  /**
   * This function performs the first iteration of LSH
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
100
  async lshInitial(): Promise<void> {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
101
    this._weights = Array(this._queryWindow.length).fill(1);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
102
    const t0 = new Date().getTime();
103
104
    this.loadingText = 'Calculating optimal LSH parameters';
    this._lshParameters = await this.api.getParameters();
105
    this.loadingText = 'Creating LSH model';
106
    const lshData = await this.api.lshUpdate(this._queryWindow, this._weights, this._lshParameters);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
107
    this.computedTime = new Date().getTime() - t0;
108
109
    this.loadingText = '';
    this.lshData = lshData;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
110
111
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
112
113
114
  /**
   * This function performs every other iteration of LSH
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
115
  async update(labels, hashFunctions): Promise<void> {
116
    this.loadingText = 'Calculating new model parameters';
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
117
    this._weights = await this.api.getWeights(this._queryWindow, labels, this._weights, hashFunctions);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
118
    const t0 = new Date().getTime();
119
    this.loadingText = 'Creating LSH model';
120
    const lshData = await this.api.lshUpdate(this._queryWindow, this._weights, this._lshParameters);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
121
    this.computedTime = new Date().getTime() - t0;
122
123
    this.loadingText = '';
    this.lshData = lshData;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
124
125
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
126
127
128
  /**
   * This function retrieves additional information given a table
   */
129
130
  async getTableInfo(table: number[][]): Promise<TableInfoData> {
    return await this.api.getTableInfo(table);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
131
132
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
133
134
135
  /**
   * This function retrieves the query
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
136
137
  async getQueryWindow(windowIndex: number | {[index: number]: boolean}, querySize, startIndex): Promise<number[][]> {
    this.queryWindow = await this.api.getQueryWindow(windowIndex, querySize, startIndex);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
138
    console.log('Printing query:');
139
    console.log(this.queryWindow);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
140
141
142
    return this._queryWindow;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
143
144
145
  /**
   * This function retrieves the window given the window index
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
146
  async getWindow(indices: number[]): Promise<number[][][]> {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
147
148
149
    return await this.api.getWindowByIndices(indices);
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
150
  public async saveState() {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
151
152
153
154
155
156
157
158
159
160
    this.maxStateIndex++;
    if (this.currStateIndex > 0) {
      if (!this.states[this.currStateIndex].children) {
        this.states[this.currStateIndex].children = [];
      }
      this.states[this.currStateIndex].children.push(this.maxStateIndex);
    }
    this.states[this.maxStateIndex] = {
      id: this.maxStateIndex,
      state: this.state,
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
161
      image: undefined,
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
162
163
      children: undefined
    };
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
164
    console.log(this.states[this.maxStateIndex]);
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
165
166
167
168
169
170
171
172
173
174
175
176
177
    this.currStateIndex = this.maxStateIndex;
  }

  public loadState(stateIndex) {
    const stateNode = this.states[stateIndex];
    this.currStateIndex = Number(stateNode.id);
    this._lshData = stateNode.state.lshData;
    this.queryWindow = stateNode.state.queryWindow;
    this._weights = stateNode.state.weights;
    this.labels = stateNode.state.labels;
    this.onNewLshData.emit();
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
178
179
180
  /**
   * These are all setters and getters
   */
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
181
  public set rawData(v: RawData[]) {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
182
183
184
185
    this._rawData = v;
    this.onNewData.emit();
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
186
  public get rawData(): RawData []{
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
187
188
189
190
191
    return this._rawData;
  }

  public set lshData(v: LshData) {
    this._lshData = v;
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
192
193
    this.saveState();
    console.log(this.states);
194
    this.onNewLshData.emit();
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  }

  public get lshData(): LshData {
    return this._lshData;
  }

  public set labels(v) {
    this._labels = v;
    this.onNewLabels.emit();
  }

  public get labels() {
    return this._labels;
  }

  public set currentTab(v: number) {
    this._currentTab = v;
    this.onNewTab.emit();
  }

  public get currentTab(): number {
    return this._currentTab;
  }

  public set sliderValue(v: number) {
    this._sliderValue = v;
    this.onNewSlider.emit(v);
  }

  public get sliderValue(): number {
    return this._sliderValue;
  }

228
229
230
231
232
233
234
235
236
  public set selection(v: number[]) {
    this._selection = v;
    this.onNewSelection.emit(v);
  }

  public get selection(): number[] {
    return this._selection;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
237
  public set queryWindow(v: number[][]) {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
238
239
240
241
    this._queryWindow = v;
    this.onNewQuery.emit();
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
242
  public get queryWindow(): number[][] {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
243
244
245
    return this._queryWindow;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
246
247
248
249
  public get lshParameters(): number[] {
    return this._lshParameters;
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
250
  public get parameters(): Parameters {
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
251
252
253
254
255
256
257
    return {
      windowsize: this.windowSize,
      hashsize: this.hashSize,
      tablesize: this.nrOfTables,
      stepsize: this.stepSize
    };
  }
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
258

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
259
260
261
262
263
264
  public get colors(): string[] {
    return ['#377eb8', '#ff7f00', '#4daf4a',
      '#f781bf', '#a65628', '#984ea3',
      '#999999', '#e41a1c', '#dede00'];
  }

Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
265
266
267
268
269
270
271
272
  public get state(): State {
    return {
      lshData: this.lshData,
      queryWindow: this.queryWindow,
      weights: this._weights,
      labels: this.labels
    };
  }
Kruyff,D.L.W. (Dylan)'s avatar
Kruyff,D.L.W. (Dylan) committed
273
}