put y axis definition into its own object
This commit is contained in:
@@ -208,9 +208,9 @@ export class PlotRequest {
|
|||||||
|
|
||||||
export class YAxisDefinition {
|
export class YAxisDefinition {
|
||||||
axisScale : string;
|
axisScale : string;
|
||||||
yRangeMin : number;
|
rangeMin : number;
|
||||||
yRangeMax : number;
|
rangeMax : number;
|
||||||
yRangeUnit : string;
|
rangeUnit : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PlotResponse {
|
export class PlotResponse {
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
<pdb-limit-by #limitbycomponent></pdb-limit-by>
|
<pdb-limit-by #limitbycomponent></pdb-limit-by>
|
||||||
|
|
||||||
|
|
||||||
<pdb-y-axis-definition #yAxisDefinitionComponent></pdb-y-axis-definition>
|
<pdb-y-axis-definition #y1AxisDefinitionComponent yIndex="1"></pdb-y-axis-definition>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<mat-checkbox [(ngModel)]="enableGallery">Gallery</mat-checkbox>
|
<mat-checkbox [(ngModel)]="enableGallery">Gallery</mat-checkbox>
|
||||||
@@ -77,7 +78,8 @@
|
|||||||
#plotView
|
#plotView
|
||||||
(zoomRange)="zoomRange($event)"
|
(zoomRange)="zoomRange($event)"
|
||||||
(zoomWithDateAnchor)="zoomWithDateAnchor($event)"></pdb-plot-view>
|
(zoomWithDateAnchor)="zoomWithDateAnchor($event)"></pdb-plot-view>
|
||||||
<pdb-gallery-view>
|
<pdb-gallery-view
|
||||||
|
#galleryView>
|
||||||
</pdb-gallery-view>
|
</pdb-gallery-view>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -28,19 +28,23 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
|
|
||||||
groupBy = new Array<TagField>();
|
groupBy = new Array<TagField>();
|
||||||
|
|
||||||
@ViewChild(LimitByComponent, {static: false})
|
@ViewChild('limitbycomponent', {static: false})
|
||||||
private limitbycomponent : LimitByComponent;
|
private limitbycomponent : LimitByComponent;
|
||||||
|
|
||||||
@ViewChild(YAxisDefinitionComponent, {static: false})
|
|
||||||
private yAxisDefinitionComponent : YAxisDefinitionComponent;
|
|
||||||
|
|
||||||
@ViewChild(QueryAutocompleteComponent, {static: false})
|
@ViewChild('y1AxisDefinitionComponent', {static: false, read: YAxisDefinitionComponent})
|
||||||
|
private y1AxisDefinitionComponent : YAxisDefinitionComponent;
|
||||||
|
|
||||||
|
@ViewChild('y2AxisDefinitionComponent', {static: false, read: YAxisDefinitionComponent})
|
||||||
|
private y2AxisDefinitionComponent : YAxisDefinitionComponent;
|
||||||
|
|
||||||
|
@ViewChild('query', {static: false})
|
||||||
query: QueryAutocompleteComponent;
|
query: QueryAutocompleteComponent;
|
||||||
|
|
||||||
@ViewChild(PlotViewComponent, {static: false})
|
@ViewChild('plotView', {static: false})
|
||||||
plotView: PlotViewComponent;
|
plotView: PlotViewComponent;
|
||||||
|
|
||||||
@ViewChild(GalleryViewComponent, {static: false})
|
@ViewChild('galleryView', {static: false})
|
||||||
galleryView: GalleryViewComponent;
|
galleryView: GalleryViewComponent;
|
||||||
|
|
||||||
enableGallery = false;
|
enableGallery = false;
|
||||||
@@ -139,11 +143,8 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
const aggregates = [];
|
const aggregates = [];
|
||||||
this.selectedPlotType.forEach(a => aggregates.push(a.id));
|
this.selectedPlotType.forEach(a => aggregates.push(a.id));
|
||||||
|
|
||||||
const y1 = new YAxisDefinition();
|
const y1 = this.y1AxisDefinitionComponent.getAxisDefinition();
|
||||||
y1.axisScale = this.yAxisDefinitionComponent.yAxisScale;
|
const y2 = this.y2AxisDefinitionComponent.getAxisDefinition();
|
||||||
y1.yRangeMin = this.yAxisDefinitionComponent.minYValue;
|
|
||||||
y1.yRangeMax = this.yAxisDefinitionComponent.maxYValue;
|
|
||||||
y1.yRangeUnit = this.yAxisDefinitionComponent.yAxisUnit;
|
|
||||||
|
|
||||||
const request = new PlotRequest();
|
const request = new PlotRequest();
|
||||||
request.query = this.query.query;
|
request.query = this.query.query;
|
||||||
@@ -153,6 +154,7 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
request.limitBy = this.limitbycomponent.limitBy;
|
request.limitBy = this.limitbycomponent.limitBy;
|
||||||
request.limit = this.limitbycomponent.limit;
|
request.limit = this.limitbycomponent.limit;
|
||||||
request.y1 = y1;
|
request.y1 = y1;
|
||||||
|
request.y2 = y2;
|
||||||
request.dateRange = this.dateRangeAsString();
|
request.dateRange = this.dateRangeAsString();
|
||||||
request.aggregates = aggregates;
|
request.aggregates = aggregates;
|
||||||
request.keyOutside = false;
|
request.keyOutside = false;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Y-Axis:</mat-label>
|
<mat-label>Y{{yIndex}}-Axis:</mat-label>
|
||||||
<mat-select [(value)]="yAxisScale">
|
<mat-select [(value)]="yAxisScale">
|
||||||
<mat-option value="LOG10">Logarithm</mat-option>
|
<mat-option value="LOG10">Logarithm</mat-option>
|
||||||
<mat-option value="LINEAR">Linear</mat-option>
|
<mat-option value="LINEAR">Linear</mat-option>
|
||||||
@@ -9,7 +8,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field class="pdb-form-mid">
|
<mat-form-field class="pdb-form-mid">
|
||||||
<mat-label>Y-Axis Range:</mat-label>
|
<mat-label>Y{{yIndex}}-Axis Range:</mat-label>
|
||||||
<mat-select [(value)]="yAxisUnit">
|
<mat-select [(value)]="yAxisUnit">
|
||||||
<mat-option value="AUTOMATIC">automatic</mat-option>
|
<mat-option value="AUTOMATIC">automatic</mat-option>
|
||||||
<mat-option value="MILLISECONDS">millis</mat-option>
|
<mat-option value="MILLISECONDS">millis</mat-option>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { YAxisDefinition } from '../plot.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pdb-y-axis-definition',
|
selector: 'pdb-y-axis-definition',
|
||||||
@@ -7,12 +8,23 @@ import { Component, Input } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class YAxisDefinitionComponent {
|
export class YAxisDefinitionComponent {
|
||||||
|
|
||||||
|
|
||||||
yAxisScale: string = "LOG10";
|
yAxisScale: string = "LOG10";
|
||||||
yAxisUnit: string = "SECONDS";
|
yAxisUnit: string = "SECONDS";
|
||||||
minYValue: number = 0;
|
minYValue: number = 0;
|
||||||
maxYValue: number = 300;
|
maxYValue: number = 300;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
yIndex: string = "";
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAxisDefinition() {
|
||||||
|
const result = new YAxisDefinition();
|
||||||
|
result.axisScale = this.yAxisScale;
|
||||||
|
result.rangeMin = this.minYValue;
|
||||||
|
result.rangeMax = this.maxYValue;
|
||||||
|
result.rangeUnit = this.yAxisUnit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ public class AggregatorCollection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addValue(final Tags groupedBy, final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final Tags groupedBy, final long epochMilli, final long value) {
|
||||||
for (final CustomAggregator aggregator : aggregators.values()) {
|
for (final CustomAggregator aggregator : aggregators.values()) {
|
||||||
aggregator.addValue(valueIsInYRange, epochMilli, value);
|
aggregator.addValue(epochMilli, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class BarChartAggregator implements CustomAggregator, IndexedAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addValue(final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final long epochMilli, final long value) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,13 +58,16 @@ public class BarChartHandler extends AggregateHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
AxisSettings createYAxisSettings(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
|
AxisSettings createYAxisSettings(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
|
||||||
|
|
||||||
|
final GnuplotAxis yAxis = getyAxis();
|
||||||
|
|
||||||
final AxisSettings result = new AxisSettings();
|
final AxisSettings result = new AxisSettings();
|
||||||
result.setLabel("Count");
|
result.setLabel("Count");
|
||||||
result.setType(Type.Number);
|
result.setType(Type.Number);
|
||||||
result.setAxis(getyAxis());
|
result.setAxis(yAxis);
|
||||||
result.setTicsEnabled(true);
|
result.setTicsEnabled(true);
|
||||||
result.setFrom("0");
|
result.setFrom("0");
|
||||||
result.setLogscale(settings.getYAxisScale() == AxisScale.LOG10);
|
result.setLogscale(settings.getYAxisDefinition(yAxis).isLogscale());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class CumulativeDistributionCustomAggregator implements CustomAggregator
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addValue(final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final long epochMilli, final long value) {
|
||||||
map.compute(value, 0, l -> l + 1);
|
map.compute(value, 0, l -> l + 1);
|
||||||
totalValues++;
|
totalValues++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.lucares.pdb.plot.api;
|
|||||||
|
|
||||||
public interface CustomAggregator {
|
public interface CustomAggregator {
|
||||||
|
|
||||||
void addValue(boolean valueIsInYRange, long epochMilli, long value);
|
void addValue(long epochMilli, long value);
|
||||||
|
|
||||||
AggregatedData getAggregatedData();
|
AggregatedData getAggregatedData();
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class HistogramAggregator implements CustomAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addValue(final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final long epochMilli, final long value) {
|
||||||
map.compute(value, 0, l -> l + 1);
|
map.compute(value, 0, l -> l + 1);
|
||||||
min = min < value ? min : value;
|
min = min < value ? min : value;
|
||||||
max = max > value ? max : value;
|
max = max > value ? max : value;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class ParallelRequestsAggregator implements CustomAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addValue(final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final long epochMilli, final long value) {
|
||||||
|
|
||||||
final int endPos = (int) (epochMilli - fromEpochMilli);
|
final int endPos = (int) (epochMilli - fromEpochMilli);
|
||||||
increments[endPos]--;
|
increments[endPos]--;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.util.List;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.lucares.pdb.api.DateTimeRange;
|
import org.lucares.pdb.api.DateTimeRange;
|
||||||
|
import org.lucares.recommind.logs.GnuplotAxis;
|
||||||
import org.lucares.utils.Preconditions;
|
import org.lucares.utils.Preconditions;
|
||||||
|
|
||||||
public class PlotSettings {
|
public class PlotSettings {
|
||||||
@@ -32,14 +33,11 @@ public class PlotSettings {
|
|||||||
|
|
||||||
private String dateRangeAsString;
|
private String dateRangeAsString;
|
||||||
|
|
||||||
private AxisScale yAxisScale;
|
private YAxisDefinition y1;
|
||||||
|
private YAxisDefinition y2;
|
||||||
|
|
||||||
private AggregateHandlerCollection aggregates;
|
private AggregateHandlerCollection aggregates;
|
||||||
|
|
||||||
private int yRangeMin;
|
|
||||||
private int yRangeMax;
|
|
||||||
private TimeRangeUnit yRangeUnit = TimeRangeUnit.AUTOMATIC;
|
|
||||||
|
|
||||||
private boolean keyOutside;
|
private boolean keyOutside;
|
||||||
|
|
||||||
private boolean generateThumbnail;
|
private boolean generateThumbnail;
|
||||||
@@ -128,21 +126,12 @@ public class PlotSettings {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYAxisScale(final AxisScale axisScale) {
|
|
||||||
this.yAxisScale = axisScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AxisScale getYAxisScale() {
|
|
||||||
return yAxisScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PlotSettings [query=" + query + ", height=" + height + ", width=" + width + ", thumbnailMaxWidth="
|
return "PlotSettings [query=" + query + ", height=" + height + ", width=" + width + ", thumbnailMaxWidth="
|
||||||
+ thumbnailMaxWidth + ", thumbnailMaxHeight=" + thumbnailMaxHeight + ", groupBy=" + groupBy
|
+ thumbnailMaxWidth + ", thumbnailMaxHeight=" + thumbnailMaxHeight + ", groupBy=" + groupBy
|
||||||
+ ", limitBy=" + limitBy + ", limit=" + limit + ", dateRangeAsString=" + dateRangeAsString
|
+ ", limitBy=" + limitBy + ", limit=" + limit + ", dateRangeAsString=" + dateRangeAsString + ", y1="
|
||||||
+ ", yAxisScale=" + yAxisScale + ", aggregates=" + aggregates + ", yRangeMin=" + yRangeMin
|
+ y1 + " y2=" + y2 + ", aggregates=" + aggregates + ", keyOutside=" + keyOutside
|
||||||
+ ", yRangeMax=" + yRangeMax + ", yRangeUnit=" + yRangeUnit + ", keyOutside=" + keyOutside
|
|
||||||
+ ", generateThumbnail=" + generateThumbnail + "]";
|
+ ", generateThumbnail=" + generateThumbnail + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,28 +159,31 @@ public class PlotSettings {
|
|||||||
return generateThumbnail;
|
return generateThumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYRangeMin() {
|
public YAxisDefinition getY1() {
|
||||||
return yRangeMin;
|
return y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYRangeMin(final int yRangeMin) {
|
public void setY1(final YAxisDefinition y1) {
|
||||||
this.yRangeMin = yRangeMin;
|
this.y1 = y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYRangeMax() {
|
public YAxisDefinition getY2() {
|
||||||
return yRangeMax;
|
return y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYRangeMax(final int yRangeMax) {
|
public void setY2(final YAxisDefinition y2) {
|
||||||
this.yRangeMax = yRangeMax;
|
this.y2 = y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeRangeUnit getYRangeUnit() {
|
public YAxisDefinition getyAxisDefinition(final GnuplotAxis yAxis) {
|
||||||
return yRangeUnit;
|
switch (yAxis) {
|
||||||
}
|
case Y1:
|
||||||
|
return y1;
|
||||||
|
case Y2:
|
||||||
|
return y2;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected value: " + yAxis);
|
||||||
|
}
|
||||||
|
|
||||||
public void setYRangeUnit(final TimeRangeUnit yRangeUnit) {
|
|
||||||
this.yRangeUnit = yRangeUnit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class ScatterAggregateHandler extends AggregateHandler {
|
|||||||
public CustomAggregator createCustomAggregator(final Path tmpDir, final PlotSettings plotSettings,
|
public CustomAggregator createCustomAggregator(final Path tmpDir, final PlotSettings plotSettings,
|
||||||
final long fromEpochMilli, final long toEpochMilli) {
|
final long fromEpochMilli, final long toEpochMilli) {
|
||||||
|
|
||||||
return new ScatterAggregator(tmpDir, plotSettings, fromEpochMilli, toEpochMilli);
|
return new ScatterAggregator(tmpDir, plotSettings, getyAxis(), fromEpochMilli, toEpochMilli);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import org.lucares.collections.Sparse2DLongArray;
|
import org.lucares.collections.Sparse2DLongArray;
|
||||||
import org.lucares.pdb.api.RuntimeIOException;
|
import org.lucares.pdb.api.RuntimeIOException;
|
||||||
|
import org.lucares.recommind.logs.GnuplotAxis;
|
||||||
import org.lucares.recommind.logs.GnuplotSettings;
|
import org.lucares.recommind.logs.GnuplotSettings;
|
||||||
import org.lucares.recommind.logs.LambdaFriendlyWriter;
|
import org.lucares.recommind.logs.LambdaFriendlyWriter;
|
||||||
import org.lucares.recommind.logs.LongUtils;
|
import org.lucares.recommind.logs.LongUtils;
|
||||||
@@ -32,8 +33,8 @@ public class ScatterAggregator implements CustomAggregator {
|
|||||||
|
|
||||||
private final Path tmpDir;
|
private final Path tmpDir;
|
||||||
|
|
||||||
public ScatterAggregator(final Path tmpDir, final PlotSettings plotSettings, final long fromEpochMilli,
|
public ScatterAggregator(final Path tmpDir, final PlotSettings plotSettings, final GnuplotAxis yAxis,
|
||||||
final long toEpochMilli) {
|
final long fromEpochMilli, final long toEpochMilli) {
|
||||||
|
|
||||||
this.tmpDir = tmpDir;
|
this.tmpDir = tmpDir;
|
||||||
useMillis = (toEpochMilli - fromEpochMilli) < TimeUnit.MINUTES.toMillis(5);
|
useMillis = (toEpochMilli - fromEpochMilli) < TimeUnit.MINUTES.toMillis(5);
|
||||||
@@ -41,17 +42,18 @@ public class ScatterAggregator implements CustomAggregator {
|
|||||||
plotAreaHeightInPx = plotSettings.getHeight() - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
|
plotAreaHeightInPx = plotSettings.getHeight() - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
|
||||||
epochMillisPerPixel = Math.max(1, (toEpochMilli - fromEpochMilli) / plotAreaWidthInPx);
|
epochMillisPerPixel = Math.max(1, (toEpochMilli - fromEpochMilli) / plotAreaWidthInPx);
|
||||||
|
|
||||||
minValue = plotSettings.getYRangeUnit() == TimeRangeUnit.AUTOMATIC ? 0
|
final YAxisDefinition yAxisDefinition = plotSettings.getyAxisDefinition(yAxis);
|
||||||
: plotSettings.getYRangeUnit().toMilliSeconds(plotSettings.getYRangeMin());
|
|
||||||
maxValue = plotSettings.getYRangeUnit() == TimeRangeUnit.AUTOMATIC ? Long.MAX_VALUE
|
minValue = yAxisDefinition.getRangeUnit() == TimeRangeUnit.AUTOMATIC ? 0 : yAxisDefinition.getRangeMinInMs();
|
||||||
: plotSettings.getYRangeUnit().toMilliSeconds(plotSettings.getYRangeMax());
|
maxValue = yAxisDefinition.getRangeUnit() == TimeRangeUnit.AUTOMATIC ? Long.MAX_VALUE
|
||||||
durationMillisPerPixel = plotSettings.getYAxisScale() == AxisScale.LINEAR
|
: yAxisDefinition.getRangeMaxInMs();
|
||||||
|
durationMillisPerPixel = yAxisDefinition.getAxisScale() == AxisScale.LINEAR
|
||||||
? Math.max(1, (maxValue - minValue) / plotAreaHeightInPx)
|
? Math.max(1, (maxValue - minValue) / plotAreaHeightInPx)
|
||||||
: 1;
|
: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addValue(final boolean valueIsInYRange, final long epochMilli, final long value) {
|
public void addValue(final long epochMilli, final long value) {
|
||||||
final long roundedEpochMilli = epochMilli - epochMilli % epochMillisPerPixel;
|
final long roundedEpochMilli = epochMilli - epochMilli % epochMillisPerPixel;
|
||||||
final long roundedValue = value - value % durationMillisPerPixel;
|
final long roundedValue = value - value % durationMillisPerPixel;
|
||||||
matrix2d.put(roundedEpochMilli, roundedValue, 1);
|
matrix2d.put(roundedEpochMilli, roundedValue, 1);
|
||||||
|
|||||||
@@ -1,41 +1,58 @@
|
|||||||
package org.lucares.pdb.plot.api;
|
package org.lucares.pdb.plot.api;
|
||||||
|
|
||||||
public class YAxisDefinition {
|
public class YAxisDefinition {
|
||||||
private AxisScale yAxisScale = AxisScale.LINEAR;
|
private AxisScale axisScale = AxisScale.LINEAR;
|
||||||
|
|
||||||
private int yRangeMin = 0;
|
private int rangeMin = 0;
|
||||||
private int yRangeMax = 300;
|
private int rangeMax = 300;
|
||||||
private TimeRangeUnit yRangeUnit = TimeRangeUnit.AUTOMATIC;
|
private TimeRangeUnit rangeUnit = TimeRangeUnit.AUTOMATIC;
|
||||||
|
|
||||||
public AxisScale getAxisScale() {
|
public AxisScale getAxisScale() {
|
||||||
return yAxisScale;
|
return axisScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAxisScale(final AxisScale yAxis) {
|
public void setAxisScale(final AxisScale axisScale) {
|
||||||
this.yAxisScale = yAxis;
|
this.axisScale = axisScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getyRangeMin() {
|
public long getRangeMinInMs() {
|
||||||
return yRangeMin;
|
return rangeUnit.toMilliSeconds(rangeMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setyRangeMin(final int yRangeMin) {
|
public long getRangeMaxInMs() {
|
||||||
this.yRangeMin = yRangeMin;
|
return rangeUnit.toMilliSeconds(rangeMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getyRangeMax() {
|
public int getRangeMin() {
|
||||||
return yRangeMax;
|
return rangeMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setyRangeMax(final int yRangeMax) {
|
public boolean hasRange() {
|
||||||
this.yRangeMax = yRangeMax;
|
return rangeUnit != TimeRangeUnit.AUTOMATIC && rangeMin >= 0 && rangeMax >= 0 && rangeMin < rangeMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeRangeUnit getyRangeUnit() {
|
public void setRangeMin(final int rangeMin) {
|
||||||
return yRangeUnit;
|
this.rangeMin = rangeMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setyRangeUnit(final TimeRangeUnit yRangeUnit) {
|
public int getRangeMax() {
|
||||||
this.yRangeUnit = yRangeUnit;
|
return rangeMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRangeMax(final int rangeMax) {
|
||||||
|
this.rangeMax = rangeMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeRangeUnit getRangeUnit() {
|
||||||
|
return rangeUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRangeUnit(final TimeRangeUnit rangeUnit) {
|
||||||
|
this.rangeUnit = rangeUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLogscale() {
|
||||||
|
return axisScale == AxisScale.LOG10;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import org.lucares.collections.LongList;
|
import org.lucares.collections.LongList;
|
||||||
import org.lucares.pdb.api.DateTimeRange;
|
import org.lucares.pdb.api.DateTimeRange;
|
||||||
import org.lucares.pdb.plot.api.AxisScale;
|
import org.lucares.pdb.plot.api.AxisScale;
|
||||||
|
import org.lucares.pdb.plot.api.YAxisDefinition;
|
||||||
import org.lucares.recommind.logs.AxisSettings.Type;
|
import org.lucares.recommind.logs.AxisSettings.Type;
|
||||||
|
|
||||||
public class AxisTime {
|
public class AxisTime {
|
||||||
@@ -40,25 +41,30 @@ public class AxisTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static AxisSettings createYAxis(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
|
public static AxisSettings createYAxis(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
|
||||||
|
|
||||||
|
final GnuplotAxis yAxis = GnuplotAxis.Y1; // TODO get yAxis as parameter
|
||||||
|
|
||||||
final AxisSettings result = new AxisSettings();
|
final AxisSettings result = new AxisSettings();
|
||||||
result.setLabel("Duration");
|
result.setLabel("Duration");
|
||||||
result.setType(Type.Duration);
|
result.setType(Type.Duration);
|
||||||
result.setAxis(GnuplotAxis.Y1);
|
result.setAxis(yAxis);
|
||||||
result.setTicsEnabled(true);
|
result.setTicsEnabled(true);
|
||||||
|
|
||||||
final int graphOffset = settings.getYAxisScale() == AxisScale.LINEAR ? 0 : 1;
|
final YAxisDefinition yAxisDefinition = settings.getYAxisDefinition(yAxis);
|
||||||
if (settings.hasYRange()) {
|
|
||||||
final int min = Math.max(settings.getYRangeMin(), graphOffset);
|
final int graphOffset = yAxisDefinition.getAxisScale() == AxisScale.LINEAR ? 0 : 1;
|
||||||
final int max = settings.getYRangeMax();
|
if (yAxisDefinition.hasRange()) {
|
||||||
|
final long min = Math.max(yAxisDefinition.getRangeMinInMs(), graphOffset);
|
||||||
|
final long max = yAxisDefinition.getRangeMaxInMs();
|
||||||
result.setFrom(String.valueOf(min));
|
result.setFrom(String.valueOf(min));
|
||||||
result.setTo(String.valueOf(max));
|
result.setTo(String.valueOf(max));
|
||||||
} else {
|
} else {
|
||||||
result.setFrom(String.valueOf(graphOffset));
|
result.setFrom(String.valueOf(graphOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.setLogscale(settings.getYAxisScale() == AxisScale.LOG10);
|
result.setLogscale(yAxisDefinition.isLogscale());
|
||||||
|
|
||||||
result.setTics(YAxisTicks.computeYTicks(settings, dataSeries));
|
result.setTics(YAxisTicks.computeYTicks(settings, yAxis, dataSeries));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ class CsvSummary {
|
|||||||
private final long maxValue;
|
private final long maxValue;
|
||||||
private final AggregatorCollection aggregators;
|
private final AggregatorCollection aggregators;
|
||||||
private final double statsAverage;
|
private final double statsAverage;
|
||||||
private final int plottedValues;
|
|
||||||
|
|
||||||
public CsvSummary(final int values, final int plottedValues, final long maxValue, final double statsAverage,
|
public CsvSummary(final int values, final long maxValue, final double statsAverage,
|
||||||
final AggregatorCollection aggregators) {
|
final AggregatorCollection aggregators) {
|
||||||
super();
|
super();
|
||||||
this.values = values;
|
this.values = values;
|
||||||
this.plottedValues = plottedValues;
|
|
||||||
this.maxValue = maxValue;
|
this.maxValue = maxValue;
|
||||||
this.statsAverage = statsAverage;
|
this.statsAverage = statsAverage;
|
||||||
this.aggregators = aggregators;
|
this.aggregators = aggregators;
|
||||||
@@ -29,16 +27,6 @@ class CsvSummary {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of plotted values in the selected date range <em>and</em> y-range.
|
|
||||||
*
|
|
||||||
* @see CsvSummary#getValues()
|
|
||||||
* @return number of plotted values
|
|
||||||
*/
|
|
||||||
public int getPlottedValues() {
|
|
||||||
return plottedValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMaxValue() {
|
public long getMaxValue() {
|
||||||
return maxValue;
|
return maxValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ public interface DataSeries {
|
|||||||
|
|
||||||
public int getValues();
|
public int getValues();
|
||||||
|
|
||||||
public int getPlottedValues();
|
|
||||||
|
|
||||||
public long getMaxValue();
|
public long getMaxValue();
|
||||||
|
|
||||||
public double getAverage();
|
public double getAverage();
|
||||||
|
|||||||
@@ -48,11 +48,6 @@ public class FileBackedDataSeries implements DataSeries {
|
|||||||
return csvSummary.getValues();
|
return csvSummary.getValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPlottedValues() {
|
|
||||||
return csvSummary.getPlottedValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getMaxValue() {
|
public long getMaxValue() {
|
||||||
return csvSummary.getMaxValue();
|
return csvSummary.getMaxValue();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.nio.file.Path;
|
|||||||
|
|
||||||
import org.lucares.pdb.api.DateTimeRange;
|
import org.lucares.pdb.api.DateTimeRange;
|
||||||
import org.lucares.pdb.plot.api.AggregateHandlerCollection;
|
import org.lucares.pdb.plot.api.AggregateHandlerCollection;
|
||||||
import org.lucares.pdb.plot.api.AxisScale;
|
import org.lucares.pdb.plot.api.YAxisDefinition;
|
||||||
|
|
||||||
public class GnuplotSettings {
|
public class GnuplotSettings {
|
||||||
|
|
||||||
@@ -27,14 +27,13 @@ public class GnuplotSettings {
|
|||||||
// set output "datausage.png"
|
// set output "datausage.png"
|
||||||
private final Path output;
|
private final Path output;
|
||||||
|
|
||||||
private AxisScale yAxisScale;
|
private YAxisDefinition y1;
|
||||||
|
private YAxisDefinition y2;
|
||||||
private AggregateHandlerCollection aggregates;
|
private AggregateHandlerCollection aggregates;
|
||||||
private boolean keyOutside = false;
|
private boolean keyOutside = false;
|
||||||
|
|
||||||
private AxisSettings xAxisSettings = new AxisSettings();
|
private AxisSettings xAxisSettings = new AxisSettings();
|
||||||
private boolean renderLabels = true;
|
private boolean renderLabels = true;
|
||||||
private int yRangeMin = -1;
|
|
||||||
private int yRangeMax = -1;
|
|
||||||
private DateTimeRange dateTimeRange;
|
private DateTimeRange dateTimeRange;
|
||||||
|
|
||||||
public GnuplotSettings(final Path output) {
|
public GnuplotSettings(final Path output) {
|
||||||
@@ -93,14 +92,6 @@ public class GnuplotSettings {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYAxisScale(final AxisScale yAxisScale) {
|
|
||||||
this.yAxisScale = yAxisScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AxisScale getYAxisScale() {
|
|
||||||
return yAxisScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAggregates(final AggregateHandlerCollection aggregates) {
|
public void setAggregates(final AggregateHandlerCollection aggregates) {
|
||||||
this.aggregates = aggregates;
|
this.aggregates = aggregates;
|
||||||
}
|
}
|
||||||
@@ -125,24 +116,23 @@ public class GnuplotSettings {
|
|||||||
return renderLabels;
|
return renderLabels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasYRange() {
|
public YAxisDefinition getY1() {
|
||||||
return yRangeMin >= 0 && yRangeMax >= 0 && yRangeMin < yRangeMax;
|
return y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYRange(final int yRangeMin, final int yRangeMax) {
|
public void setY1(final YAxisDefinition y1) {
|
||||||
this.yRangeMin = yRangeMin;
|
this.y1 = y1;
|
||||||
this.yRangeMax = yRangeMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYRangeMin() {
|
public YAxisDefinition getY2() {
|
||||||
return yRangeMin;
|
return y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYRangeMax() {
|
public void setY2(final YAxisDefinition y2) {
|
||||||
return yRangeMax;
|
this.y2 = y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDateTimeRange(DateTimeRange dateTimeRange) {
|
public void setDateTimeRange(final DateTimeRange dateTimeRange) {
|
||||||
this.dateTimeRange = dateTimeRange;
|
this.dateTimeRange = dateTimeRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +140,17 @@ public class GnuplotSettings {
|
|||||||
return dateTimeRange;
|
return dateTimeRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public YAxisDefinition getYAxisDefinition(final GnuplotAxis yAxis) {
|
||||||
|
switch (yAxis) {
|
||||||
|
case Y1:
|
||||||
|
return y1;
|
||||||
|
case Y2:
|
||||||
|
return y2;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected value: " + yAxis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// plot 'sample.txt' using 1:2 title 'Bytes' with linespoints 2
|
// plot 'sample.txt' using 1:2 title 'Bytes' with linespoints 2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.lucares.pdb.api.Tags;
|
|||||||
import org.lucares.pdb.plot.api.AggregatorCollection;
|
import org.lucares.pdb.plot.api.AggregatorCollection;
|
||||||
import org.lucares.pdb.plot.api.Limit;
|
import org.lucares.pdb.plot.api.Limit;
|
||||||
import org.lucares.pdb.plot.api.PlotSettings;
|
import org.lucares.pdb.plot.api.PlotSettings;
|
||||||
import org.lucares.pdb.plot.api.TimeRangeUnit;
|
|
||||||
import org.lucares.performance.db.PerformanceDb;
|
import org.lucares.performance.db.PerformanceDb;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -108,10 +107,10 @@ public class Plotter {
|
|||||||
gnuplotSettings.setWidth(width);
|
gnuplotSettings.setWidth(width);
|
||||||
gnuplotSettings.setDateTimeRange(plotSettings.dateRange());
|
gnuplotSettings.setDateTimeRange(plotSettings.dateRange());
|
||||||
|
|
||||||
gnuplotSettings.setYAxisScale(plotSettings.getYAxisScale());
|
gnuplotSettings.setY1(plotSettings.getY1());
|
||||||
|
gnuplotSettings.setY2(plotSettings.getY2());
|
||||||
|
|
||||||
gnuplotSettings.setAggregates(plotSettings.getAggregates());
|
gnuplotSettings.setAggregates(plotSettings.getAggregates());
|
||||||
defineYRange(gnuplotSettings, plotSettings.getYRangeMin(), plotSettings.getYRangeMax(),
|
|
||||||
plotSettings.getYRangeUnit());
|
|
||||||
gnuplotSettings.setKeyOutside(plotSettings.isKeyOutside());
|
gnuplotSettings.setKeyOutside(plotSettings.isKeyOutside());
|
||||||
gnuplot.plot(gnuplotSettings, dataSeries);
|
gnuplot.plot(gnuplotSettings, dataSeries);
|
||||||
}
|
}
|
||||||
@@ -124,11 +123,9 @@ public class Plotter {
|
|||||||
gnuplotSettings.setHeight(plotSettings.getThumbnailMaxHeight());
|
gnuplotSettings.setHeight(plotSettings.getThumbnailMaxHeight());
|
||||||
gnuplotSettings.setWidth(plotSettings.getThumbnailMaxWidth());
|
gnuplotSettings.setWidth(plotSettings.getThumbnailMaxWidth());
|
||||||
gnuplotSettings.setDateTimeRange(plotSettings.dateRange());
|
gnuplotSettings.setDateTimeRange(plotSettings.dateRange());
|
||||||
|
gnuplotSettings.setY1(plotSettings.getY1());
|
||||||
gnuplotSettings.setYAxisScale(plotSettings.getYAxisScale());
|
gnuplotSettings.setY2(plotSettings.getY2());
|
||||||
gnuplotSettings.setAggregates(plotSettings.getAggregates());
|
gnuplotSettings.setAggregates(plotSettings.getAggregates());
|
||||||
defineYRange(gnuplotSettings, plotSettings.getYRangeMin(), plotSettings.getYRangeMax(),
|
|
||||||
plotSettings.getYRangeUnit());
|
|
||||||
gnuplotSettings.setKeyOutside(false);
|
gnuplotSettings.setKeyOutside(false);
|
||||||
gnuplotSettings.renderLabels(false);
|
gnuplotSettings.renderLabels(false);
|
||||||
gnuplot.plot(gnuplotSettings, dataSeries);
|
gnuplot.plot(gnuplotSettings, dataSeries);
|
||||||
@@ -148,16 +145,6 @@ public class Plotter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void defineYRange(final GnuplotSettings gnuplotSettings, final int yRangeMin, final int yRangeMax,
|
|
||||||
final TimeRangeUnit yRangeUnit) {
|
|
||||||
|
|
||||||
if (yRangeUnit != TimeRangeUnit.AUTOMATIC) {
|
|
||||||
final int min = yRangeUnit.toMilliSeconds(yRangeMin);
|
|
||||||
final int max = yRangeUnit.toMilliSeconds(yRangeMax);
|
|
||||||
gnuplotSettings.setYRange(min, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CsvSummary toCsvDeduplicated(final GroupResult groupResult, final Path tmpDir,
|
private static CsvSummary toCsvDeduplicated(final GroupResult groupResult, final Path tmpDir,
|
||||||
final OffsetDateTime dateFrom, final OffsetDateTime dateTo, final PlotSettings plotSettings)
|
final OffsetDateTime dateFrom, final OffsetDateTime dateTo, final PlotSettings plotSettings)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@@ -169,16 +156,11 @@ public class Plotter {
|
|||||||
final long toEpochMilli = dateTo.toInstant().toEpochMilli();
|
final long toEpochMilli = dateTo.toInstant().toEpochMilli();
|
||||||
final boolean useMillis = (toEpochMilli - fromEpochMilli) < TimeUnit.MINUTES.toMillis(5);
|
final boolean useMillis = (toEpochMilli - fromEpochMilli) < TimeUnit.MINUTES.toMillis(5);
|
||||||
|
|
||||||
final long minValue = plotSettings.getYRangeUnit() == TimeRangeUnit.AUTOMATIC ? 0
|
|
||||||
: plotSettings.getYRangeUnit().toMilliSeconds(plotSettings.getYRangeMin());
|
|
||||||
final long maxValue = plotSettings.getYRangeUnit() == TimeRangeUnit.AUTOMATIC ? Long.MAX_VALUE
|
|
||||||
: plotSettings.getYRangeUnit().toMilliSeconds(plotSettings.getYRangeMax());
|
|
||||||
|
|
||||||
final AggregatorCollection aggregator = plotSettings.getAggregates().createCustomAggregator(tmpDir,
|
final AggregatorCollection aggregator = plotSettings.getAggregates().createCustomAggregator(tmpDir,
|
||||||
plotSettings, fromEpochMilli, toEpochMilli);
|
plotSettings, fromEpochMilli, toEpochMilli);
|
||||||
|
|
||||||
int count = 0; // number of values in the x-axis range (used to compute stats)
|
int count = 0; // number of values in the x-axis range (used to compute stats)
|
||||||
int plottedValues = 0;
|
final int plottedValues = 0;
|
||||||
long statsMaxValue = 0;
|
long statsMaxValue = 0;
|
||||||
double statsCurrentAverage = 0.0;
|
double statsCurrentAverage = 0.0;
|
||||||
long ignoredValues = 0;
|
long ignoredValues = 0;
|
||||||
@@ -204,22 +186,14 @@ public class Plotter {
|
|||||||
// compute average (important to do this after 'count' has been incremented)
|
// compute average (important to do this after 'count' has been incremented)
|
||||||
statsCurrentAverage = statsCurrentAverage + (value - statsCurrentAverage) / count;
|
statsCurrentAverage = statsCurrentAverage + (value - statsCurrentAverage) / count;
|
||||||
|
|
||||||
// check if value is in the selected y-range
|
aggregator.addValue(groupedBy, epochMilli, value);
|
||||||
final boolean valueIsInYRange = value < minValue || value > maxValue;
|
|
||||||
if (valueIsInYRange) {
|
|
||||||
ignoredValues++;
|
|
||||||
} else {
|
|
||||||
plottedValues++;
|
|
||||||
}
|
|
||||||
|
|
||||||
aggregator.addValue(groupedBy, valueIsInYRange, epochMilli, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
METRICS_LOGGER.debug("wrote {} values to csv in: {}ms (ignored {} values) use millis: {}, grouping={}",
|
METRICS_LOGGER.debug("wrote {} values to csv in: {}ms (ignored {} values) use millis: {}, grouping={}",
|
||||||
plottedValues, (System.nanoTime() - start) / 1_000_000.0, ignoredValues, Boolean.toString(useMillis),
|
plottedValues, (System.nanoTime() - start) / 1_000_000.0, ignoredValues, Boolean.toString(useMillis),
|
||||||
groupResult.getGroupedBy().asString());
|
groupResult.getGroupedBy().asString());
|
||||||
return new CsvSummary(count, plottedValues, statsMaxValue, statsCurrentAverage, aggregator);
|
return new CsvSummary(count, statsMaxValue, statsCurrentAverage, aggregator);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,17 +203,13 @@ public class Plotter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String title(final Tags tags, final CsvSummary csvSummary) {
|
static String title(final Tags tags, final CsvSummary csvSummary) {
|
||||||
|
// FIXME title must be computed by the AggregateHandler, because it is the only
|
||||||
|
// one knowing how many values are plotted
|
||||||
final StringBuilder result = new StringBuilder(tags.asValueString());
|
final StringBuilder result = new StringBuilder(tags.asValueString());
|
||||||
|
|
||||||
final int values = csvSummary.getValues();
|
final int values = csvSummary.getValues();
|
||||||
final int plottedValues = csvSummary.getPlottedValues();
|
|
||||||
result.append(" (");
|
result.append(" (");
|
||||||
if (plottedValues != values) {
|
result.append(String.format("%,d", values));
|
||||||
result.append(String.format("%,d / %,d", plottedValues, values));
|
|
||||||
} else {
|
|
||||||
result.append(String.format("%,d", values));
|
|
||||||
}
|
|
||||||
result.append(")");
|
result.append(")");
|
||||||
|
|
||||||
return result.toString();
|
return result.toString();
|
||||||
|
|||||||
@@ -12,23 +12,28 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.lucares.pdb.plot.api.YAxisDefinition;
|
||||||
|
|
||||||
class YAxisTicks {
|
class YAxisTicks {
|
||||||
|
|
||||||
public static List<String> computeYTicks(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
|
public static List<String> computeYTicks(final GnuplotSettings settings, final GnuplotAxis yAxis,
|
||||||
|
final Collection<DataSeries> dataSeries) {
|
||||||
List<String> result = new ArrayList<String>();
|
List<String> result = new ArrayList<String>();
|
||||||
|
|
||||||
|
final YAxisDefinition yAxisDefinition = settings.getYAxisDefinition(yAxis);
|
||||||
|
|
||||||
final long yRangeMax;
|
final long yRangeMax;
|
||||||
final long yRangeMin;
|
final long yRangeMin;
|
||||||
if (settings.hasYRange()) {
|
if (yAxisDefinition.hasRange()) {
|
||||||
yRangeMax = settings.getYRangeMax();
|
yRangeMin = yAxisDefinition.getRangeMinInMs();
|
||||||
yRangeMin = settings.getYRangeMin();
|
yRangeMax = yAxisDefinition.getRangeMaxInMs();
|
||||||
} else {
|
} else {
|
||||||
yRangeMax = DataSeries.maxValue(dataSeries);
|
|
||||||
yRangeMin = 0;
|
yRangeMin = 0;
|
||||||
|
yRangeMax = DataSeries.maxValue(dataSeries);
|
||||||
}
|
}
|
||||||
final int height = settings.getHeight();
|
final int height = settings.getHeight();
|
||||||
|
|
||||||
switch (settings.getYAxisScale()) {
|
switch (yAxisDefinition.getAxisScale()) {
|
||||||
case LINEAR:
|
case LINEAR:
|
||||||
result = computeLinearYTicks(height, yRangeMin, yRangeMax);
|
result = computeLinearYTicks(height, yRangeMin, yRangeMax);
|
||||||
break;
|
break;
|
||||||
@@ -81,16 +86,17 @@ class YAxisTicks {
|
|||||||
return ticsLabels;
|
return ticsLabels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> computeLinearYTicks(final long height, final long yRangeMin, final long yRangeMax) {
|
private static List<String> computeLinearYTicks(final long height, final long yRangeMinInMs,
|
||||||
|
final long yRangeMaxInMs) {
|
||||||
|
|
||||||
final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
|
final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
|
||||||
final long maxLabels = plotHeight / (GnuplotSettings.TICKS_FONT_SIZE * 5);
|
final long maxLabels = plotHeight / (GnuplotSettings.TICKS_FONT_SIZE * 5);
|
||||||
|
|
||||||
final long range = yRangeMax - yRangeMin;
|
final long range = yRangeMaxInMs - yRangeMinInMs;
|
||||||
final long msPerLabel = roundToLinearLabelSteps(range / maxLabels);
|
final long msPerLabel = roundToLinearLabelSteps(range / maxLabels);
|
||||||
|
|
||||||
final List<String> ticsLabels = new ArrayList<>();
|
final List<String> ticsLabels = new ArrayList<>();
|
||||||
for (long i = yRangeMin; i <= yRangeMax; i += msPerLabel) {
|
for (long i = yRangeMinInMs; i <= yRangeMaxInMs; i += msPerLabel) {
|
||||||
ticsLabels.add("\"" + msToTic(i, msPerLabel) + "\" " + i);
|
ticsLabels.add("\"" + msToTic(i, msPerLabel) + "\" " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
package org.lucares.pdbui;
|
package org.lucares.pdbui;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -23,9 +20,6 @@ import org.lucares.pdb.api.DateTimeRange;
|
|||||||
import org.lucares.pdb.api.QueryWithCaretMarker;
|
import org.lucares.pdb.api.QueryWithCaretMarker;
|
||||||
import org.lucares.pdb.api.QueryWithCaretMarker.ResultMode;
|
import org.lucares.pdb.api.QueryWithCaretMarker.ResultMode;
|
||||||
import org.lucares.pdb.datastore.Proposal;
|
import org.lucares.pdb.datastore.Proposal;
|
||||||
import org.lucares.pdb.plot.api.Aggregate;
|
|
||||||
import org.lucares.pdb.plot.api.AxisScale;
|
|
||||||
import org.lucares.pdb.plot.api.Limit;
|
|
||||||
import org.lucares.pdb.plot.api.PlotSettings;
|
import org.lucares.pdb.plot.api.PlotSettings;
|
||||||
import org.lucares.pdbui.domain.AutocompleteProposal;
|
import org.lucares.pdbui.domain.AutocompleteProposal;
|
||||||
import org.lucares.pdbui.domain.AutocompleteProposalByValue;
|
import org.lucares.pdbui.domain.AutocompleteProposalByValue;
|
||||||
@@ -48,7 +42,6 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.util.StreamUtils;
|
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -60,7 +53,6 @@ import org.springframework.web.bind.annotation.RequestPart;
|
|||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
@@ -156,65 +148,64 @@ public class PdbController implements HardcodedValues, PropertyKeys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(path = "/plots", //
|
/*
|
||||||
method = RequestMethod.GET, //
|
* @RequestMapping(path = "/plots", // method = RequestMethod.GET, // produces =
|
||||||
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE //
|
* MediaType.APPLICATION_OCTET_STREAM_VALUE // ) StreamingResponseBody
|
||||||
)
|
* createPlotImage(@RequestParam(name = "query", defaultValue = "") final String
|
||||||
StreamingResponseBody createPlotImage(@RequestParam(name = "query", defaultValue = "") final String query,
|
* query,
|
||||||
@RequestParam(name = "groupBy[]", defaultValue = "") final List<String> aGroupBy,
|
*
|
||||||
@RequestParam(name = "limitBy.number", defaultValue = "10") final int limit,
|
* @RequestParam(name = "groupBy[]", defaultValue = "") final List<String>
|
||||||
@RequestParam(name = "limitBy.selected", defaultValue = "NO_LIMIT") final Limit limitBy,
|
* aGroupBy,
|
||||||
@RequestParam(name = "dateRange") final String dateRange,
|
*
|
||||||
@RequestParam(name = "axisScale", defaultValue = "LINEAR") final AxisScale axisScale,
|
* @RequestParam(name = "limitBy.number", defaultValue = "10") final int limit,
|
||||||
@RequestParam(name = "aggregates") final EnumSet<Aggregate> aggregate,
|
*
|
||||||
@RequestParam(name = "keyOutside", defaultValue = "false") final boolean keyOutside,
|
* @RequestParam(name = "limitBy.selected", defaultValue = "NO_LIMIT") final
|
||||||
@RequestParam(name = "width", defaultValue = "1920") final int hidth,
|
* Limit limitBy,
|
||||||
@RequestParam(name = "height", defaultValue = "1080") final int height) {
|
*
|
||||||
return (final OutputStream outputStream) -> {
|
* @RequestParam(name = "dateRange") final String dateRange,
|
||||||
|
*
|
||||||
if (StringUtils.isBlank(query)) {
|
* @RequestParam(name = "axisScale", defaultValue = "LINEAR") final AxisScale
|
||||||
throw new BadRequest("The query must not be empty!");
|
* axisScale,
|
||||||
}
|
*
|
||||||
|
* @RequestParam(name = "aggregates") final EnumSet<Aggregate> aggregate,
|
||||||
if (StringUtils.isBlank(dateRange)) {
|
*
|
||||||
throw new BadRequest("The parameter 'dateRange' must be set.");
|
* @RequestParam(name = "keyOutside", defaultValue = "false") final boolean
|
||||||
}
|
* keyOutside,
|
||||||
|
*
|
||||||
final PlotSettings plotSettings = new PlotSettings();
|
* @RequestParam(name = "width", defaultValue = "1920") final int hidth,
|
||||||
plotSettings.setQuery(query);
|
*
|
||||||
plotSettings.setGroupBy(aGroupBy);
|
* @RequestParam(name = "height", defaultValue = "1080") final int height) {
|
||||||
plotSettings.setHeight(height);
|
* return (final OutputStream outputStream) -> {
|
||||||
plotSettings.setWidth(hidth);
|
*
|
||||||
plotSettings.setLimit(limit);
|
* if (StringUtils.isBlank(query)) { throw new
|
||||||
plotSettings.setLimitBy(limitBy);
|
* BadRequest("The query must not be empty!"); }
|
||||||
plotSettings.setDateRange(dateRange);
|
*
|
||||||
plotSettings.setYAxisScale(axisScale);
|
* if (StringUtils.isBlank(dateRange)) { throw new
|
||||||
plotSettings.setAggregates(PlotSettingsTransformer.toAggregateInternal(plotSettings.getYRangeUnit(),
|
* BadRequest("The parameter 'dateRange' must be set."); }
|
||||||
plotSettings.getYAxisScale(), aggregate));
|
*
|
||||||
plotSettings.setKeyOutside(keyOutside);
|
* final PlotSettings plotSettings = new PlotSettings();
|
||||||
plotSettings.setGenerateThumbnail(false);
|
* plotSettings.setQuery(query); plotSettings.setGroupBy(aGroupBy);
|
||||||
|
* plotSettings.setHeight(height); plotSettings.setWidth(hidth);
|
||||||
if (plotterLock.tryLock()) {
|
* plotSettings.setLimit(limit); plotSettings.setLimitBy(limitBy);
|
||||||
try {
|
* plotSettings.setDateRange(dateRange); plotSettings.setY1(y1);
|
||||||
final PlotResult result = plotter.plot(plotSettings);
|
* plotSettings.setYAxisScale(axisScale);
|
||||||
|
* plotSettings.setAggregates(PlotSettingsTransformer.toAggregateInternal(
|
||||||
try (FileInputStream in = new FileInputStream(result.getImagePath().toFile())) {
|
* plotSettings.getYRangeUnit(), plotSettings.getYAxisScale(), aggregate));
|
||||||
StreamUtils.copy(in, outputStream);
|
* plotSettings.setKeyOutside(keyOutside);
|
||||||
}
|
* plotSettings.setGenerateThumbnail(false);
|
||||||
} catch (final NoDataPointsException e) {
|
*
|
||||||
throw new NotFoundException(e);
|
* if (plotterLock.tryLock()) { try { final PlotResult result =
|
||||||
} catch (final InternalPlottingException e) {
|
* plotter.plot(plotSettings);
|
||||||
throw new InternalServerError(e);
|
*
|
||||||
} finally {
|
* try (FileInputStream in = new
|
||||||
plotterLock.unlock();
|
* FileInputStream(result.getImagePath().toFile())) { StreamUtils.copy(in,
|
||||||
}
|
* outputStream); } } catch (final NoDataPointsException e) { throw new
|
||||||
|
* NotFoundException(e); } catch (final InternalPlottingException e) { throw new
|
||||||
} else {
|
* InternalServerError(e); } finally { plotterLock.unlock(); }
|
||||||
throw new ServiceUnavailableException("Too many parallel requests!");
|
*
|
||||||
}
|
* } else { throw new
|
||||||
};
|
* ServiceUnavailableException("Too many parallel requests!"); } }; }
|
||||||
}
|
*/
|
||||||
|
|
||||||
@RequestMapping(path = "/autocomplete", //
|
@RequestMapping(path = "/autocomplete", //
|
||||||
method = RequestMethod.GET, //
|
method = RequestMethod.GET, //
|
||||||
produces = MediaType.APPLICATION_JSON_VALUE //
|
produces = MediaType.APPLICATION_JSON_VALUE //
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.lucares.pdbui;
|
package org.lucares.pdbui;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.lucares.pdb.plot.api.Aggregate;
|
import org.lucares.pdb.plot.api.Aggregate;
|
||||||
import org.lucares.pdb.plot.api.AggregateHandlerCollection;
|
import org.lucares.pdb.plot.api.AggregateHandlerCollection;
|
||||||
import org.lucares.pdb.plot.api.AxisScale;
|
import org.lucares.pdb.plot.api.AxisScale;
|
||||||
@@ -10,6 +12,7 @@ import org.lucares.pdb.plot.api.ParallelRequestsAggregate;
|
|||||||
import org.lucares.pdb.plot.api.PlotSettings;
|
import org.lucares.pdb.plot.api.PlotSettings;
|
||||||
import org.lucares.pdb.plot.api.ScatterAggregateHandler;
|
import org.lucares.pdb.plot.api.ScatterAggregateHandler;
|
||||||
import org.lucares.pdb.plot.api.TimeRangeUnit;
|
import org.lucares.pdb.plot.api.TimeRangeUnit;
|
||||||
|
import org.lucares.pdb.plot.api.YAxisDefinition;
|
||||||
import org.lucares.pdbui.domain.PlotRequest;
|
import org.lucares.pdbui.domain.PlotRequest;
|
||||||
|
|
||||||
class PlotSettingsTransformer {
|
class PlotSettingsTransformer {
|
||||||
@@ -24,40 +27,20 @@ class PlotSettingsTransformer {
|
|||||||
result.setLimit(request.getLimit());
|
result.setLimit(request.getLimit());
|
||||||
result.setLimitBy(request.getLimitBy());
|
result.setLimitBy(request.getLimitBy());
|
||||||
result.setDateRange(request.getDateRange());
|
result.setDateRange(request.getDateRange());
|
||||||
result.setYAxisScale(request.getY1().getAxisScale());
|
|
||||||
result.setKeyOutside(request.isKeyOutside());
|
result.setKeyOutside(request.isKeyOutside());
|
||||||
result.setThumbnailMaxWidth(request.getThumbnailMaxWidth());
|
result.setThumbnailMaxWidth(request.getThumbnailMaxWidth());
|
||||||
result.setThumbnailMaxHeight(request.getThumbnailMaxHeight());
|
result.setThumbnailMaxHeight(request.getThumbnailMaxHeight());
|
||||||
result.setGenerateThumbnail(request.isGenerateThumbnail());
|
result.setGenerateThumbnail(request.isGenerateThumbnail());
|
||||||
result.setYRangeMin(request.getY1().getyRangeMin());
|
result.setY1(request.getY1());
|
||||||
result.setYRangeMax(request.getY1().getyRangeMax());
|
result.setY2(request.getY2());
|
||||||
result.setYRangeUnit(toTimeRangeUnitInternal(request.getY1().getyRangeUnit()));
|
result.setAggregates(toAggregateInternal(request.getY1(), request.getY2(), request.getAggregates()));
|
||||||
result.setAggregates(
|
|
||||||
toAggregateInternal(result.getYRangeUnit(), result.getYAxisScale(), request.getAggregates()));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeRangeUnit toTimeRangeUnitInternal(final TimeRangeUnit yRangeUnit) {
|
static AggregateHandlerCollection toAggregateInternal(final YAxisDefinition y1, final YAxisDefinition y2,
|
||||||
switch (yRangeUnit) {
|
final List<Aggregate> aggregates) {
|
||||||
case AUTOMATIC:
|
|
||||||
return TimeRangeUnit.AUTOMATIC;
|
|
||||||
case MILLISECONDS:
|
|
||||||
return TimeRangeUnit.MILLISECONDS;
|
|
||||||
case SECONDS:
|
|
||||||
return TimeRangeUnit.SECONDS;
|
|
||||||
case MINUTES:
|
|
||||||
return TimeRangeUnit.MINUTES;
|
|
||||||
case HOURS:
|
|
||||||
return TimeRangeUnit.HOURS;
|
|
||||||
case DAYS:
|
|
||||||
return TimeRangeUnit.DAYS;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("unhandled enum value: " + yRangeUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static AggregateHandlerCollection toAggregateInternal(final TimeRangeUnit yRangeUnit, final AxisScale yAxisScale,
|
|
||||||
final Iterable<Aggregate> aggregates) {
|
|
||||||
final AggregateHandlerCollection aggregateHandlerCollection = new AggregateHandlerCollection();
|
final AggregateHandlerCollection aggregateHandlerCollection = new AggregateHandlerCollection();
|
||||||
|
|
||||||
for (final Aggregate aggregate : aggregates) {
|
for (final Aggregate aggregate : aggregates) {
|
||||||
@@ -70,14 +53,7 @@ class PlotSettingsTransformer {
|
|||||||
aggregateHandlerCollection.addAggregateHandler(new ParallelRequestsAggregate());
|
aggregateHandlerCollection.addAggregateHandler(new ParallelRequestsAggregate());
|
||||||
break;
|
break;
|
||||||
case SCATTER:
|
case SCATTER:
|
||||||
if (yRangeUnit == TimeRangeUnit.AUTOMATIC && yAxisScale == AxisScale.LINEAR) {
|
aggregateHandlerCollection.addAggregateHandler(new ScatterAggregateHandler());
|
||||||
// TODO need a second ScatterAggregateHandler for YRangeUnit() ==
|
|
||||||
// TimeRangeUnitInternal.AUTOMATIC
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"linear axis with automatic y range does not work, use logarthmic y-axis, or define a y-axis range");
|
|
||||||
} else {
|
|
||||||
aggregateHandlerCollection.addAggregateHandler(new ScatterAggregateHandler());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case HISTOGRAM:
|
case HISTOGRAM:
|
||||||
aggregateHandlerCollection.addAggregateHandler(new HistogramHandler());
|
aggregateHandlerCollection.addAggregateHandler(new HistogramHandler());
|
||||||
@@ -92,6 +68,14 @@ class PlotSettingsTransformer {
|
|||||||
|
|
||||||
aggregateHandlerCollection.updateAxisForHandlers();
|
aggregateHandlerCollection.updateAxisForHandlers();
|
||||||
|
|
||||||
|
// Note: this check is incomplete -> implement the todo and remove this
|
||||||
|
if (y1.getRangeUnit() == TimeRangeUnit.AUTOMATIC && y1.getAxisScale() == AxisScale.LINEAR) {
|
||||||
|
// TODO need a second ScatterAggregateHandler for YRangeUnit() ==
|
||||||
|
// TimeRangeUnitInternal.AUTOMATIC
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"linear axis with automatic y range does not work, use logarthmic y-axis, or define a y-axis range");
|
||||||
|
}
|
||||||
|
|
||||||
return aggregateHandlerCollection;
|
return aggregateHandlerCollection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ public class DataSeriesStats {
|
|||||||
private final int values;
|
private final int values;
|
||||||
private final long maxValue;
|
private final long maxValue;
|
||||||
private final double average;
|
private final double average;
|
||||||
private final int plottedValues;
|
|
||||||
|
|
||||||
public DataSeriesStats(final int values, final int plottedValues, final long maxValue, final double average) {
|
public DataSeriesStats(final int values, final long maxValue, final double average) {
|
||||||
this.values = values;
|
this.values = values;
|
||||||
this.plottedValues = plottedValues;
|
|
||||||
this.maxValue = maxValue;
|
this.maxValue = maxValue;
|
||||||
this.average = average;
|
this.average = average;
|
||||||
}
|
}
|
||||||
@@ -24,15 +22,6 @@ public class DataSeriesStats {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of values in the date range <em>and</em> the y-range.
|
|
||||||
*
|
|
||||||
* @return number of plotted values
|
|
||||||
*/
|
|
||||||
public int getPlottedValues() {
|
|
||||||
return plottedValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMaxValue() {
|
public long getMaxValue() {
|
||||||
return maxValue;
|
return maxValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,20 +12,17 @@ public class PlotResponseStats {
|
|||||||
|
|
||||||
private double average;
|
private double average;
|
||||||
|
|
||||||
private int plottedValues;
|
|
||||||
|
|
||||||
private List<DataSeriesStats> dataSeriesStats;
|
private List<DataSeriesStats> dataSeriesStats;
|
||||||
|
|
||||||
public PlotResponseStats() {
|
public PlotResponseStats() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlotResponseStats(final long maxValue, final int values, final int plottedValues, final double average,
|
public PlotResponseStats(final long maxValue, final int values, final double average,
|
||||||
final List<DataSeriesStats> dataSeriesStats) {
|
final List<DataSeriesStats> dataSeriesStats) {
|
||||||
|
|
||||||
this.maxValue = maxValue;
|
this.maxValue = maxValue;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
this.plottedValues = plottedValues;
|
|
||||||
this.average = average;
|
this.average = average;
|
||||||
this.dataSeriesStats = dataSeriesStats;
|
this.dataSeriesStats = dataSeriesStats;
|
||||||
}
|
}
|
||||||
@@ -46,14 +43,6 @@ public class PlotResponseStats {
|
|||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPlottedValues() {
|
|
||||||
return plottedValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlottedValues(final int plottedValues) {
|
|
||||||
this.plottedValues = plottedValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getAverage() {
|
public double getAverage() {
|
||||||
return average;
|
return average;
|
||||||
}
|
}
|
||||||
@@ -73,27 +62,25 @@ public class PlotResponseStats {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PlotResponseStats [maxValue=" + maxValue + ", values=" + values + ", average=" + average
|
return "PlotResponseStats [maxValue=" + maxValue + ", values=" + values + ", average=" + average
|
||||||
+ ", plottedValues=" + plottedValues + ", dataSeriesStats=" + dataSeriesStats + "]";
|
+ ", dataSeriesStats=" + dataSeriesStats + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlotResponseStats fromDataSeries(final List<DataSeries> dataSeries) {
|
public static PlotResponseStats fromDataSeries(final List<DataSeries> dataSeries) {
|
||||||
|
|
||||||
int values = 0;
|
int values = 0;
|
||||||
int plottedValues = 0;
|
|
||||||
long maxValue = 0;
|
long maxValue = 0;
|
||||||
final List<DataSeriesStats> dataSeriesStats = new ArrayList<>();
|
final List<DataSeriesStats> dataSeriesStats = new ArrayList<>();
|
||||||
|
|
||||||
for (final DataSeries dataSerie : dataSeries) {
|
for (final DataSeries dataSerie : dataSeries) {
|
||||||
values += dataSerie.getValues();
|
values += dataSerie.getValues();
|
||||||
plottedValues += dataSerie.getPlottedValues();
|
|
||||||
maxValue = Math.max(maxValue, dataSerie.getMaxValue());
|
maxValue = Math.max(maxValue, dataSerie.getMaxValue());
|
||||||
|
|
||||||
dataSeriesStats.add(new DataSeriesStats(dataSerie.getValues(), dataSerie.getPlottedValues(),
|
dataSeriesStats
|
||||||
dataSerie.getMaxValue(), dataSerie.getAverage()));
|
.add(new DataSeriesStats(dataSerie.getValues(), dataSerie.getMaxValue(), dataSerie.getAverage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
final double average = Math.round(DataSeriesStats.average(dataSeriesStats));
|
final double average = Math.round(DataSeriesStats.average(dataSeriesStats));
|
||||||
|
|
||||||
return new PlotResponseStats(maxValue, values, plottedValues, average, dataSeriesStats);
|
return new PlotResponseStats(maxValue, values, average, dataSeriesStats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ public class DataSeriesStatsTest {
|
|||||||
|
|
||||||
{
|
{
|
||||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||||
new DataSeriesStats(10, 0, 0, 5.0)//
|
new DataSeriesStats(10, 0, 5.0)//
|
||||||
);
|
);
|
||||||
final double expected = 5.0;
|
final double expected = 5.0;
|
||||||
result.add(Arguments.of(stats, expected));
|
result.add(Arguments.of(stats, expected));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||||
new DataSeriesStats(0, 0, 0, 5.0)//
|
new DataSeriesStats(0, 0, 5.0)//
|
||||||
);
|
);
|
||||||
final double expected = 0.0; // no values
|
final double expected = 0.0; // no values
|
||||||
result.add(Arguments.of(stats, expected));
|
result.add(Arguments.of(stats, expected));
|
||||||
@@ -32,17 +32,17 @@ public class DataSeriesStatsTest {
|
|||||||
|
|
||||||
{
|
{
|
||||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||||
new DataSeriesStats(10, 0, 0, 5.0), //
|
new DataSeriesStats(10, 0, 5.0), //
|
||||||
new DataSeriesStats(40, 0, 0, 1.0)//
|
new DataSeriesStats(40, 0, 1.0)//
|
||||||
);
|
);
|
||||||
final double expected = 1.8; // 90 / 50
|
final double expected = 1.8; // 90 / 50
|
||||||
result.add(Arguments.of(stats, expected));
|
result.add(Arguments.of(stats, expected));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||||
new DataSeriesStats(5, 0, 0, 7.0), //
|
new DataSeriesStats(5, 0, 7.0), //
|
||||||
new DataSeriesStats(0, 0, 0, 5.0), // // no values
|
new DataSeriesStats(0, 0, 5.0), // // no values
|
||||||
new DataSeriesStats(20, 0, 0, 2.0)//
|
new DataSeriesStats(20, 0, 2.0)//
|
||||||
);
|
);
|
||||||
final double expected = 3.0; // (35+40) / 25
|
final double expected = 3.0; // (35+40) / 25
|
||||||
result.add(Arguments.of(stats, expected));
|
result.add(Arguments.of(stats, expected));
|
||||||
|
|||||||
Reference in New Issue
Block a user