Skip to content
Snippets Groups Projects
Commit 443a0c3b authored by Karolína Dočkalová Burská's avatar Karolína Dočkalová Burská
Browse files

Merge branch '3-indicate-insufficient-data' into 'master'

Resolve "Indicate insufficient data"

Closes #3

See merge request !4
parents 5dbf7c8a 84dc3d3f
No related branches found
No related tags found
1 merge request!4Resolve "Indicate insufficient data"
Pipeline #211507 passed
# KYPO Trainings Clustering Visualization # KYPO Trainings Clustering Visualization
## Prerequisites The visualization provides three views with distinct processing of collected data - a subset of features that define the trainee behavior and enable us to explore outliers or trainee strategies during their gameplay.
To use the library you need to have installed:
## How to use json-server as mock backend with provided dummy data ## How to use json-server as mock backend with provided dummy data
......
14.0.2 Propagate insufficient data info for dashboard processing
14.0.1 Update API routes 14.0.1 Update API routes
14.0.0 Initial clustering library version 14.0.0 Initial clustering library version
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
*ngIf="includeInButtonToggle" *ngIf="includeInButtonToggle"
(click)="toggleChartVisibility()"> {{buttonKeyword}} helper elbow function </button> (click)="toggleChartVisibility()"> {{buttonKeyword}} helper elbow function </button>
<div [attr.style]="'display: ' + (showChart ? 'block' : 'none')"> <div [attr.style]="'display: ' + (showChart ? 'inline-block' : 'none')">
<div id="chartDiv"></div> <div id="chartDiv"></div>
<div id="helpDiv"> <div id="helpDiv">
<b>How to use this chart?</b> <b>How to use this chart?</b>
......
...@@ -10,12 +10,11 @@ import { v4 as uuid } from 'uuid'; ...@@ -10,12 +10,11 @@ import { v4 as uuid } from 'uuid';
}) })
export class LineChartComponent implements OnChanges, OnInit { export class LineChartComponent implements OnChanges, OnInit {
@Input() visualizationData: number[] = []; @Input() visualizationData: number[] = [];
@Input() trainingDefinitionId: number;
@Input() trainingInstanceId: number;
@Input() elbowNumClusters: number; @Input() elbowNumClusters: number;
@Input() includeInButtonToggle = false; @Input() includeInButtonToggle = false;
@Output() viewOpen: EventEmitter<boolean> = new EventEmitter(); @Output() viewOpen: EventEmitter<boolean> = new EventEmitter();
@Output() insufficientData: EventEmitter<boolean> = new EventEmitter();
public showChart = true; public showChart = true;
public buttonKeyword = 'Hide'; public buttonKeyword = 'Hide';
...@@ -55,9 +54,17 @@ export class LineChartComponent implements OnChanges, OnInit { ...@@ -55,9 +54,17 @@ export class LineChartComponent implements OnChanges, OnInit {
if (this.gChart != undefined) { if (this.gChart != undefined) {
this.clear(); this.clear();
} }
if (this.checkData()) {
this.createSvg(); this.createSvg();
this.drawPlot(); this.drawPlot();
} }
}
checkData() {
const isAllNothing = this.visualizationData.every((value) => value === 0 || Number.isNaN(value) || value === null);
this.insufficientData.emit(isAllNothing);
return !isAllNothing;
}
private createSvg(): void { private createSvg(): void {
this.svg = this.d3 this.svg = this.d3
......
...@@ -11,8 +11,6 @@ import { Clusterables } from '../../../models/clusterables-enum'; ...@@ -11,8 +11,6 @@ import { Clusterables } from '../../../models/clusterables-enum';
}) })
export class ScatterPlotComponent implements OnChanges, OnInit { export class ScatterPlotComponent implements OnChanges, OnInit {
@Input() visualizationData: { clusterData: any[] }; @Input() visualizationData: { clusterData: any[] };
@Input() trainingDefinitionId: number;
@Input() trainingInstanceId: number;
@Input() numOfClusters: number; @Input() numOfClusters: number;
@Input() isStandalone: boolean; @Input() isStandalone: boolean;
@Input() selectedFeature: Clusterables = 0; @Input() selectedFeature: Clusterables = 0;
...@@ -223,7 +221,10 @@ export class ScatterPlotComponent implements OnChanges, OnInit { ...@@ -223,7 +221,10 @@ export class ScatterPlotComponent implements OnChanges, OnInit {
.data(this.data) .data(this.data)
.enter() .enter()
.append('circle') .append('circle')
.attr('cx', (d: any) => this.x(this.visualizationDataService.getX(d, this.selectedFeature)) + this.margin) .attr('cx', (d: any) => {
const x = this.x(this.visualizationDataService.getX(d, this.selectedFeature));
return Number.isNaN(x) ? this.margin : x + this.margin;
})
.attr('cy', (d: any) => this.y(this.visualizationDataService.getY(d, this.selectedFeature))) .attr('cy', (d: any) => this.y(this.visualizationDataService.getY(d, this.selectedFeature)))
.attr('r', 7) .attr('r', 7)
.style('opacity', 0.5) .style('opacity', 0.5)
......
...@@ -2,18 +2,15 @@ ...@@ -2,18 +2,15 @@
<!-- the line chart is available for every graph type (it can be hidden in the form of a button) --> <!-- the line chart is available for every graph type (it can be hidden in the form of a button) -->
<kypo-viz-clustering-line-chart <kypo-viz-clustering-line-chart
[visualizationData]="lineData$" [visualizationData]="lineData$"
[trainingDefinitionId]="trainingDefinitionId"
[trainingInstanceId]="trainingInstanceIds"
[elbowNumClusters]="elbowNumClusters" [elbowNumClusters]="elbowNumClusters"
[includeInButtonToggle]="true" [includeInButtonToggle]="true"
(viewOpen)="toggleView($event)" (viewOpen)="toggleView($event)"
(insufficientData)="insufficientData($event)"
></kypo-viz-clustering-line-chart> ></kypo-viz-clustering-line-chart>
<kypo-viz-clustering-scatter-plot <kypo-viz-clustering-scatter-plot
*ngIf="selectedComponent !== 2" *ngIf="selectedComponent !== 2"
[visualizationData]="visualizationData$" [visualizationData]="visualizationData$"
[trainingDefinitionId]="trainingDefinitionId"
[trainingInstanceId]="trainingInstanceIds"
[numOfClusters]="numOfClusters" [numOfClusters]="numOfClusters"
[isStandalone]="isStandalone" [isStandalone]="isStandalone"
[selectedFeature]="selectedFeature" [selectedFeature]="selectedFeature"
......
...@@ -4,7 +4,6 @@ import { VisualizationData } from '../../models/visualization-data'; ...@@ -4,7 +4,6 @@ import { VisualizationData } from '../../models/visualization-data';
import { VisualizationsDataService } from '../../services/visualizations-data.service'; import { VisualizationsDataService } from '../../services/visualizations-data.service';
import { Clusterables } from '../../models/clusterables-enum'; import { Clusterables } from '../../models/clusterables-enum';
import { Components } from '../../models/components-enum'; import { Components } from '../../models/components-enum';
import { RadarChartComponent } from './radar-chart/radar-chart.component';
@Component({ @Component({
selector: 'kypo-clustering-visualization', selector: 'kypo-clustering-visualization',
...@@ -21,8 +20,10 @@ export class VisualizationsComponent implements OnInit, OnChanges { ...@@ -21,8 +20,10 @@ export class VisualizationsComponent implements OnInit, OnChanges {
@Input() selectedFeature: Clusterables = Clusterables.WrongFlags; // (wf 1, tah 2, nd 3) @Input() selectedFeature: Clusterables = Clusterables.WrongFlags; // (wf 1, tah 2, nd 3)
@Output() viewOpen: EventEmitter<boolean> = new EventEmitter(); @Output() viewOpen: EventEmitter<boolean> = new EventEmitter();
@Output() chartIsHidden: EventEmitter<any> = new EventEmitter();
elbowNumClusters = 15; // this ensures we dont load data after every linechart change (15 clusters should be more than enough) hideLineData = [];
elbowNumClusters = 15; // this ensures we don't load different data after every line chart change (15 clusters should be just enough)
lineData$: Observable<VisualizationData>; lineData$: Observable<VisualizationData>;
visualizationData$: Observable<VisualizationData>; visualizationData$: Observable<VisualizationData>;
...@@ -44,7 +45,6 @@ export class VisualizationsComponent implements OnInit, OnChanges { ...@@ -44,7 +45,6 @@ export class VisualizationsComponent implements OnInit, OnChanges {
private loadData() { private loadData() {
this.visualizationDataService.selectedFeature = this.selectedFeature; this.visualizationDataService.selectedFeature = this.selectedFeature;
console.log(this.level);
const lineService = this.visualizationDataService.getLineData( const lineService = this.visualizationDataService.getLineData(
this.trainingDefinitionId, this.trainingDefinitionId,
...@@ -78,4 +78,12 @@ export class VisualizationsComponent implements OnInit, OnChanges { ...@@ -78,4 +78,12 @@ export class VisualizationsComponent implements OnInit, OnChanges {
}); });
} }
} }
insufficientData(badData: boolean) {
// if we don't have enough data for sse, we should hide the remaining related
// charts as well, since they will also lack data for visualization
this.hideLineData = this.hideLineData.filter((value) => value.feature !== this.selectedFeature);
this.hideLineData.push({ hide: badData, feature: this.selectedFeature });
this.chartIsHidden.emit(this.hideLineData);
}
} }
...@@ -1656,6 +1656,18 @@ clusteringDB = function() { ...@@ -1656,6 +1656,18 @@ clusteringDB = function() {
7.665157027831233, 7.665157027831233,
3.286652416172358 3.286652416172358
], ],
sseWrong:[
NaN,
0,
0,
NaN,
NaN,
NaN,
NaN,
NaN,
NaN,
NaN
],
sseNDim: [ sseNDim: [
165, 165,
144.16192694574772, 144.16192694574772,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment