From b115d32f307777e5a1d7ee0555b8de578ad0530a Mon Sep 17 00:00:00 2001 From: nblondheim Date: Mon, 30 Dec 2024 13:30:13 -0600 Subject: [PATCH 1/2] Change to avg-max col/cell, fix help tab to chart render and multiple data array issues --- ...achievable-efficiency-graph.component.html | 10 +- .../achievable-efficiency-graph.component.ts | 231 ++++++++++++------ .../achievable-efficiency.service.ts | 37 ++- 3 files changed, 186 insertions(+), 92 deletions(-) diff --git a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.html b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.html index 2ef276bee3..36bf0338e3 100644 --- a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.html +++ b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.html @@ -37,20 +37,20 @@ Key {{ xAxisTitle }} - Achievable Efficiency (%) + Achievable Efficiency (%)
+ 'border': index < 1? '4px solid ' + defaultTraceOutlineColor : ''}">
{{point.x}} - {{point.y}} + {{point.avgMaxEffColumn}} - + Delete @@ -72,7 +72,7 @@ {{point.x}} - {{point.y}} + {{point.avgMaxEffColumn}} diff --git a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts index c61de901c9..27fb5943df 100644 --- a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts +++ b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts @@ -4,12 +4,11 @@ import { Settings } from '../../../../shared/models/settings'; import * as _ from 'lodash'; import { graphColors } from '../../../../phast/phast-report/report-graphs/graphColors'; import { FormGroup } from '../../../../../../node_modules/@angular/forms'; -import { DataPoint, SimpleChart, TraceData, TraceCoordinates } from '../../../../shared/models/plotting'; -import { AchievableEfficiencyService } from '../achievable-efficiency.service'; +import { SimpleChart, TraceData, TraceCoordinates } from '../../../../shared/models/plotting'; +import { AchievableEfficiencyService, EfficiencyPoint, EfficiencyTrace } from '../achievable-efficiency.service'; import { pumpTypeRanges } from '../../../../psat/psatConstants'; import { PlotlyService } from 'angular-plotly.js'; - @Component({ selector: 'app-achievable-efficiency-graph', templateUrl: './achievable-efficiency-graph.component.html', @@ -55,14 +54,14 @@ export class AchievableEfficiencyGraphComponent implements OnInit { firstChange: boolean = true; // Graphing / Defaults - selectedDataPoints: Array; + selectedDataPoints: Array; pointColors: Array; efficiencyChart: SimpleChart; xAxisTitle: string = "Flow Rate (gpm)"; currentPumpType: any; defaultTraceCount: number = 2; defaultTraceOutlineColor = 'rgba(0, 0, 0, .6)'; - dataPointTraces: Array; + dataPointTraces: Array; constructor(private psatService: PsatService, private achievableEfficiencyService: AchievableEfficiencyService, @@ -76,6 +75,7 @@ export class AchievableEfficiencyGraphComponent implements OnInit { ngAfterViewInit() { this.renderChart(); + this.currentPumpType = this.efficiencyForm.controls.pumpType.value; } ngOnChanges(changes: SimpleChanges) { @@ -104,13 +104,16 @@ export class AchievableEfficiencyGraphComponent implements OnInit { save() { this.achievableEfficiencyService.efficiencyChart.next(this.efficiencyChart); this.achievableEfficiencyService.selectedDataPoints.next(this.selectedDataPoints); + this.achievableEfficiencyService.dataPointTraces.next(this.dataPointTraces); } renderChart() { - this.initChartSetup(); - this.dataPointTraces = new Array(); - this.selectedDataPoints = new Array(); - this.setCalculatedTraces(); + this.pointColors = graphColors; + this.efficiencyChart = this.achievableEfficiencyService.efficiencyChart.getValue(); + this.dataPointTraces = this.achievableEfficiencyService.dataPointTraces.getValue(); + this.selectedDataPoints = this.achievableEfficiencyService.selectedDataPoints.getValue(); + this.setMaxAvgLines(); + this.setMaxAndAvgPoints(); this.newPlot(); this.save(); } @@ -122,7 +125,8 @@ export class AchievableEfficiencyGraphComponent implements OnInit { }); this.dataPointTraces.forEach(trace => { traceData.push(trace); - }) + }); + let chartLayout = JSON.parse(JSON.stringify(this.efficiencyChart.layout)); if (this.expanded && this.expandedChartDiv) { this.plotlyService.newPlot(this.expandedChartDiv.nativeElement, traceData, chartLayout, this.efficiencyChart.config) @@ -142,101 +146,145 @@ export class AchievableEfficiencyGraphComponent implements OnInit { } updateChart() { - this.setCalculatedTraces(); + this.setMaxAndAvgPoints(); this.newPlot(); this.save(); } - initChartSetup() { - this.pointColors = graphColors; - this.efficiencyChart = this.achievableEfficiencyService.efficiencyChart.getValue(); - this.selectedDataPoints = this.achievableEfficiencyService.selectedDataPoints.getValue(); - + setMaxAvgLines() { // Default line traces let maxData: TraceCoordinates = this.getMaxData(); this.efficiencyChart.data[0].x = maxData.x; this.efficiencyChart.data[0].y = maxData.y; - this.efficiencyChart.data[0].line.color = this.pointColors[0]; + this.efficiencyChart.data[0].line.color = this.getPointColor(0); let avgData: TraceCoordinates = this.getAvgData(); this.efficiencyChart.data[1].x = avgData.x; this.efficiencyChart.data[1].y = avgData.y; - this.efficiencyChart.data[1].line.color = this.pointColors[1]; + this.efficiencyChart.data[1].line.color = this.getPointColor(1); this.efficiencyChart.layout.xaxis.title.text = this.xAxisTitle; } - - getCurrentPoints(isUserDataPoint: boolean, userDataPointX?: number): Array { - let flowRateValue: number = isUserDataPoint ? userDataPointX : this.efficiencyForm.controls.flowRate.value; - let points: Array = []; - - // Y values - let efficiencyMax = this.calculateYmax(flowRateValue); - let efficiencyAvg = this.calculateYaverage(flowRateValue); - let calculatedX: number; - - if (efficiencyMax >= 0) { - calculatedX = flowRateValue; - points.push({ x: calculatedX, y: efficiencyMax }); - } - if (efficiencyAvg >= 0) { - calculatedX = flowRateValue; - points.push({ x: calculatedX, y: efficiencyAvg }); - } - - return points; - } - - setCalculatedTraces() { - let currentPoints: DataPoint[] = this.getCurrentPoints(false); + setMaxAndAvgPoints() { + let currentPoints: EfficiencyPoint[] = this.getCurrentPoints(false); let isInvalidPlot: boolean = currentPoints.some(point => isNaN(point.x) || isNaN(point.y) || !isFinite(point.x) || !isFinite(point.y) ); if (!isInvalidPlot) { this.validEfficiency = true; - currentPoints.forEach((point, i) => { - let calculatedPoint: DataPoint = { - pointColor: this.pointColors[i], - x: point.x, - y: point.y - } - let resultCoordinateTrace: TraceData = this.achievableEfficiencyService.getTraceDataFromPoint(calculatedPoint); - let yMeasureTitle = i == 0 ? 'Maximum' : 'Average'; - let hoverTemplate = 'Flow Rate' + ': %{x}
' + yMeasureTitle + ': %{y:.2r}%
' + ''; - resultCoordinateTrace.hovertemplate = hoverTemplate; - resultCoordinateTrace.marker.color = calculatedPoint.pointColor; - resultCoordinateTrace.marker.line = { - color: this.defaultTraceOutlineColor, - width: 4 - } + let maximumPoint: EfficiencyPoint = { + id: undefined, + pointColor: this.getPointColor(0), + x: currentPoints[0].x, + y: currentPoints[0].y, + name: 'Maximum', + avgMaxEffColumn: this.getAvgMaxEffColumn(currentPoints[1].y, currentPoints[0].y) + } + + if (this.selectedDataPoints.length === 0) { + this.selectedDataPoints.push(maximumPoint); + } else { + this.selectedDataPoints.shift(); + this.selectedDataPoints.unshift(maximumPoint); + } + + let maximumPointTrace = this.achievableEfficiencyService.getTraceDataFromPoint(maximumPoint); + let hoverTemplate = 'Flow Rate' + ': %{x}
' + 'Maximum' + ': %{y:.2r}%
' + ''; + maximumPointTrace.hovertemplate = hoverTemplate; + maximumPointTrace.marker.line = { + color: this.defaultTraceOutlineColor, + width: 4 + } + this.efficiencyChart.data[this.defaultTraceCount] = maximumPointTrace; + + + let averagePoint: EfficiencyPoint = { + id: undefined, + pointColor: this.getPointColor(1), + x: currentPoints[1].x, + y: currentPoints[1].y, + name: 'Average' + } + let averagePointTrace = this.achievableEfficiencyService.getTraceDataFromPoint(averagePoint); + hoverTemplate = 'Flow Rate' + ': %{x}
' + 'Average' + ': %{y:.2r}%
' + ''; + averagePointTrace.hovertemplate = hoverTemplate; + averagePointTrace.marker.line = { + color: this.defaultTraceOutlineColor, + width: 4 + } + this.efficiencyChart.data[this.defaultTraceCount + 1] = averagePointTrace; + this.cd.detectChanges(); - this.efficiencyChart.data[this.defaultTraceCount + i] = resultCoordinateTrace; - this.selectedDataPoints.splice(i, 1, calculatedPoint); - this.cd.detectChanges(); - }); } else { this.validEfficiency = false; } } - createDataPoints(graphData) { - let dataPoints: DataPoint[] = this.getCurrentPoints(true, graphData.points[0].x); - dataPoints.forEach((point, i) => { - let selectedPoint: DataPoint = { - pointColor: this.pointColors[(this.dataPointTraces.length + 2) % this.pointColors.length], - x: point.x, - y: point.y - } - let selectedPointTrace = this.achievableEfficiencyService.getTraceDataFromPoint(selectedPoint); - this.dataPointTraces.push(selectedPointTrace); - let yMeasureTitle = i == 0 ? 'Maximum' : 'Average'; - let hoverTemplate = 'Flow Rate' + ': %{x}
' + yMeasureTitle + ': %{y:.2r}%
' + ''; - selectedPointTrace.hovertemplate = hoverTemplate; - this.selectedDataPoints.push(selectedPoint); - }); + getCurrentPoints(isUserDataPoint: boolean, userDataPointX?: number): Array { + let flowRateValue: number = isUserDataPoint ? userDataPointX : this.efficiencyForm.controls.flowRate.value; + let points: Array = []; + let efficiencyMax = this.calculateYmax(flowRateValue); + let efficiencyAvg = this.calculateYaverage(flowRateValue); + + if (efficiencyMax >= 0 && efficiencyAvg >= 0) { + points.push({ + id: undefined, + pairId: undefined, + x: flowRateValue, + y: efficiencyMax, + avgMaxEffColumn: this.getAvgMaxEffColumn(efficiencyMax, efficiencyAvg) + }); + } + if (efficiencyAvg >= 0) { + points.push({ + id: undefined, + x: flowRateValue, + y: efficiencyAvg, + avgMaxEffColumn: undefined + }); + } + + return points; + } + + createDataPoints(graphData) { + let dataPoints: EfficiencyPoint[] = this.getCurrentPoints(true, graphData.points[0].x); + + let maximumPoint: EfficiencyPoint = { + id: undefined, + pairId: undefined, + pointColor: this.getPointColor(0), + x: dataPoints[0].x, + y: dataPoints[0].y, + name: 'Maximum', + avgMaxEffColumn: this.getAvgMaxEffColumn(dataPoints[1].y, dataPoints[0].y) + } + + let maximumPointTrace = this.achievableEfficiencyService.getTraceDataFromPoint(maximumPoint); + let hoverTemplate = 'Flow Rate' + ': %{x}
' + 'Maximum' + ': %{y:.2r}%
' + ''; + maximumPointTrace.hovertemplate = hoverTemplate; + + let averagePoint: EfficiencyPoint = { + id: undefined, + pointColor: this.getPointColor(1), + x: dataPoints[1].x, + y: dataPoints[1].y, + name: 'Average' + } + let averagePointTrace: EfficiencyTrace = this.achievableEfficiencyService.getTraceDataFromPoint(averagePoint); + hoverTemplate = 'Flow Rate' + ': %{x}
' + 'Average' + ': %{y:.2r}%
' + ''; + averagePointTrace.hovertemplate = hoverTemplate; + + maximumPointTrace.id = maximumPointTrace.id; + maximumPointTrace.pairId = averagePointTrace.id; + maximumPoint.id = maximumPointTrace.id; + maximumPoint.pairId = averagePointTrace.id; + + this.selectedDataPoints.push(maximumPoint); + this.dataPointTraces.push(maximumPointTrace, averagePointTrace); this.newPlot(); this.cd.detectChanges(); @@ -253,8 +301,8 @@ export class AchievableEfficiencyGraphComponent implements OnInit { } } - deleteDataPoint(point: DataPoint, index: number) { - this.dataPointTraces = this.dataPointTraces.filter(trace => { return trace.marker.color != point.pointColor }); + deleteDataPoint(deletePoint: EfficiencyPoint, index: number) { + this.dataPointTraces = this.dataPointTraces.filter(trace => { return trace.id != deletePoint.id && trace.id != deletePoint.pairId}); this.selectedDataPoints.splice(index, 1); this.newPlot(); this.cd.detectChanges(); @@ -431,4 +479,31 @@ export class AchievableEfficiencyGraphComponent implements OnInit { this.updateChart(); } + getPointColor(index: number, getRandom = false) { + let color = index % 2 === 0? this.pointColors[0] : this.pointColors[1] + if(!getRandom) { + return color; + } + // return this.getRandomOpacity(color); + return this.pointColors[(this.dataPointTraces.length + 1) % this.pointColors.length]; + } + + getAvgMaxEffColumn(avg: number, max: number) { + return `${avg} - ${max}`; + } + +// getRandomOpacity(pointColor: string) { +// const sanitizedHex = pointColor.replace("#", ""); +// const bigint = parseInt(sanitizedHex, 16); +// const r = (bigint >> 16) & 255; +// const g = (bigint >> 8) & 255; +// const b = bigint & 255; + +// const minOpacity = 0.3; +// const maxOpacity = 0.9; +// const opacity = Math.random() * (maxOpacity - minOpacity) + minOpacity; + +// return `rgba(${r}, ${g}, ${b}, ${opacity.toFixed(2)})`; +// } + } diff --git a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.service.ts b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.service.ts index d4378b06d6..d2879e5cc7 100644 --- a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.service.ts +++ b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.service.ts @@ -1,7 +1,8 @@ import { Injectable } from '@angular/core'; import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms'; -import { SimpleChart, DataPoint, TraceData } from '../../../shared/models/plotting'; +import { SimpleChart, TraceData } from '../../../shared/models/plotting'; import { BehaviorSubject } from 'rxjs'; +import { getNewIdString } from '../../../shared/helperFunctions'; @Injectable() export class AchievableEfficiencyService { @@ -9,18 +10,17 @@ export class AchievableEfficiencyService { pumpType: number; flowRate: number; efficiencyChart: BehaviorSubject; - selectedDataPoints: BehaviorSubject>; - // selectedDataPoints: BehaviorSubject>; + selectedDataPoints: BehaviorSubject>; + dataPointTraces: BehaviorSubject>; constructor(private formBuilder: UntypedFormBuilder) { this.initChartData(); } initChartData() { - let emptyChart: SimpleChart = this.getEmptyChart(); - let dataPoints = new Array(); - this.efficiencyChart = new BehaviorSubject(emptyChart); - this.selectedDataPoints = new BehaviorSubject>(dataPoints); + this.efficiencyChart = new BehaviorSubject(this.getEmptyChart()); + this.selectedDataPoints = new BehaviorSubject>([]); + this.dataPointTraces = new BehaviorSubject>([]); } @@ -35,10 +35,12 @@ export class AchievableEfficiencyService { return form; } - getTraceDataFromPoint(selectedPoint: DataPoint): TraceData { - let trace: TraceData = { + getTraceDataFromPoint(selectedPoint: EfficiencyPoint): EfficiencyTrace { + let trace: EfficiencyTrace = { x: [selectedPoint.x], y: [selectedPoint.y], + id: getNewIdString(), + pairId: undefined, type: 'scatter', name: `${selectedPoint.x}, ${selectedPoint.y}`, showlegend: false, @@ -124,3 +126,20 @@ export class AchievableEfficiencyService { } + + +export interface EfficiencyPoint { + id: string, + pairId?: string, + pointColor?: string; + pointOutlineColor?: string; + pointTraceIndex?: number; + name?: string; + x: number; + y: number; + avgMaxEffColumn?: string; +} + +export interface EfficiencyTrace extends TraceData { + pairId: string, +} \ No newline at end of file From 7ffe26aba270b8060146830a7a411cf53abd6b8a Mon Sep 17 00:00:00 2001 From: nblondheim Date: Tue, 31 Dec 2024 06:38:35 -0600 Subject: [PATCH 2/2] fix re-render issues --- .../achievable-efficiency-graph.component.ts | 31 ++----------------- .../achievable-efficiency.component.ts | 3 -- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts index 27fb5943df..64626e7bcb 100644 --- a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts +++ b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency-graph/achievable-efficiency-graph.component.ts @@ -57,8 +57,7 @@ export class AchievableEfficiencyGraphComponent implements OnInit { selectedDataPoints: Array; pointColors: Array; efficiencyChart: SimpleChart; - xAxisTitle: string = "Flow Rate (gpm)"; - currentPumpType: any; + xAxisTitle: string; defaultTraceCount: number = 2; defaultTraceOutlineColor = 'rgba(0, 0, 0, .6)'; dataPointTraces: Array; @@ -70,37 +69,23 @@ export class AchievableEfficiencyGraphComponent implements OnInit { ngOnInit() { this.xAxisTitle = `Flow Rate (${this.settings.flowMeasurement})`; - this.currentPumpType = this.efficiencyForm.controls.pumpType.value; } ngAfterViewInit() { this.renderChart(); - this.currentPumpType = this.efficiencyForm.controls.pumpType.value; } ngOnChanges(changes: SimpleChanges) { if (!this.firstChange) { - if (changes.toggleResetData) { + if (this.checkForm()) { this.achievableEfficiencyService.initChartData(); this.renderChart(); } - if (changes.toggleExampleData) { - if (this.checkForm()) { - this.achievableEfficiencyService.initChartData(); - this.renderChart(); - } - } - if (changes.toggleCalculate && !changes.toggleResetData && !changes.toggleExampleData) { - if (this.checkForm()) { - this.checkReplotMethod(); - } - } } else { this.firstChange = false; } } - save() { this.achievableEfficiencyService.efficiencyChart.next(this.efficiencyChart); this.achievableEfficiencyService.selectedDataPoints.next(this.selectedDataPoints); @@ -291,16 +276,6 @@ export class AchievableEfficiencyGraphComponent implements OnInit { this.save(); } - checkReplotMethod() { - if (this.efficiencyForm.controls.pumpType.value !== this.currentPumpType) { - this.currentPumpType = this.efficiencyForm.controls.pumpType.value; - this.achievableEfficiencyService.initChartData(); - this.renderChart(); - } else { - this.updateChart(); - } - } - deleteDataPoint(deletePoint: EfficiencyPoint, index: number) { this.dataPointTraces = this.dataPointTraces.filter(trace => { return trace.id != deletePoint.id && trace.id != deletePoint.pairId}); this.selectedDataPoints.splice(index, 1); @@ -316,7 +291,7 @@ export class AchievableEfficiencyGraphComponent implements OnInit { range: { min: 0, max: 0 }, increment: 10, }; - xRange.range = ranges.find(pumpType => pumpType.value == this.currentPumpType).range; + xRange.range = ranges.find(pumpType => pumpType.value == this.efficiencyForm.controls.pumpType.value).range; if (xRange.range.min <= 5000) { xRange.increment = 10; } else if (xRange.range.max <= 50000) { diff --git a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.component.ts b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.component.ts index a512a1bafc..20cc0dde95 100644 --- a/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.component.ts +++ b/src/app/calculator/pumps/achievable-efficiency/achievable-efficiency.component.ts @@ -148,9 +148,6 @@ export class AchievableEfficiencyComponent implements OnInit { } btnGenerateExample() { - if (!this.settings) { - this.settings = this.settingsDbService.globalSettings; - } this.generateExample(); this.toggleExampleData = !this.toggleExampleData; this.calculate();