From 5ad03f9e1c3412cd02a32b5f58459bac0bd604a5 Mon Sep 17 00:00:00 2001 From: Jim Bowring Date: Wed, 17 Aug 2022 08:38:24 -0400 Subject: [PATCH] additional plots --- .../gui/dataViews/plots/BasicLinePlot.java | 2 +- .../plots/BasicScatterAndLinePlot.java | 159 ++++++++++++++++++ .../gui/dataViews/plots/BasicScatterPlot.java | 2 +- .../RJMCMCPlots/RJMCMCPlotBuildersTask.java | 14 +- .../RJMCMCPlots/RJMCMCPlotsController.java | 110 ++++++------ .../rjmcmc/DataModelDriverExperiment.java | 56 +++--- .../linePlots/ComboPlotBuilder.java | 59 +++++++ 7 files changed, 323 insertions(+), 79 deletions(-) create mode 100644 TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterAndLinePlot.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/visualizationUtilities/linePlots/ComboPlotBuilder.java diff --git a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicLinePlot.java b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicLinePlot.java index 24cdc7c6..b7ded2b2 100644 --- a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicLinePlot.java +++ b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicLinePlot.java @@ -72,7 +72,7 @@ public void paint(GraphicsContext g2d) { g2d.fillText(intensityLinePlotBuilder.getTitle(), leftMargin + 25, 15); g2d.setLineWidth(2.0); - // new line graph + // new line plot g2d.setStroke(Paint.valueOf("Black")); g2d.beginPath(); g2d.moveTo(mapX(xAxisData[0]), mapY(yAxisData[0])); diff --git a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterAndLinePlot.java b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterAndLinePlot.java new file mode 100644 index 00000000..fcd1683f --- /dev/null +++ b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterAndLinePlot.java @@ -0,0 +1,159 @@ +package org.cirdles.tripoli.gui.dataViews.plots; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Paint; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import org.cirdles.tripoli.visualizationUtilities.linePlots.ComboPlotBuilder; + + +public class BasicScatterAndLinePlot extends AbstractDataView { + + private final ComboPlotBuilder comboPlotBuilder; + private double[] yAxisData2; + /** + * @param bounds + * @param comboPlotBuilder + */ + public BasicScatterAndLinePlot(Rectangle bounds, ComboPlotBuilder comboPlotBuilder) { + super(bounds, 50, 5); + this.comboPlotBuilder = comboPlotBuilder; + } + + @Override + public void preparePanel() { + xAxisData = comboPlotBuilder.getxData(); + yAxisData = comboPlotBuilder.getyData(); + yAxisData2 = comboPlotBuilder.getyData2(); + + minX = xAxisData[0]; + maxX = xAxisData[xAxisData.length - 1]; + + ticsX = TicGeneratorForAxes.generateTics(minX, maxX, (int) (graphWidth / 40.0)); + double xMarginStretch = TicGeneratorForAxes.generateMarginAdjustment(minX, maxX, 0.01); + minX -= xMarginStretch; + maxX += xMarginStretch; + + minY = Double.MAX_VALUE; + maxY = -Double.MAX_VALUE; + + for (int i = 0; i < yAxisData.length; i++) { + minY = StrictMath.min(minY, yAxisData[i]); + maxY = StrictMath.max(maxY, yAxisData[i]); + minY = StrictMath.min(minY, yAxisData2[i]); + maxY = StrictMath.max(maxY, yAxisData2[i]); + if (comboPlotBuilder.isyData2OneSigma()){ + minY = StrictMath.min(minY, -yAxisData2[i]); + } + } + ticsY = TicGeneratorForAxes.generateTics(minY, maxY, (int) (graphHeight / 15.0)); + if ((ticsY != null) && (ticsY.length > 1)) { + // force y to tics + minY = ticsY[0].doubleValue(); + maxY = ticsY[ticsY.length - 1].doubleValue(); + // adjust margins + double yMarginStretch = TicGeneratorForAxes.generateMarginAdjustment(minY, maxY, 0.1); + minY -= yMarginStretch * 2.0; + maxY += yMarginStretch; + } + + setDisplayOffsetY(0.0); + setDisplayOffsetX(0.0); + + this.repaint(); + } + + @Override + public void paint(GraphicsContext g2d) { + super.paint(g2d); + + Text text = new Text(); + text.setFont(Font.font("SansSerif", 12)); + int textWidth = 0; + + g2d.setFont(Font.font("SansSerif", FontWeight.SEMI_BOLD, 12)); + g2d.setFill(Paint.valueOf("BLUE")); + g2d.fillText(comboPlotBuilder.getTitle(), leftMargin + 25, 15); + + // scatter plot + g2d.setLineWidth(0.75); + g2d.setStroke(Paint.valueOf("Black")); + for (int i = 0; i < xAxisData.length; i++) { + g2d.strokeOval(mapX(xAxisData[i]) - 2f, mapY(yAxisData[i]) -2f, 4f, 4f); + } + + // new line plot from yAxisData2 + g2d.setStroke(Paint.valueOf("red")); + g2d.beginPath(); + g2d.moveTo(mapX(xAxisData[0]), mapY(yAxisData2[0])); + for (int i = 0; i < xAxisData.length; i++) { + // line tracing through points + g2d.lineTo(mapX(xAxisData[i]), mapY(yAxisData2[i])); + } + g2d.stroke(); + + if (comboPlotBuilder.isyData2OneSigma()){ + g2d.beginPath(); + g2d.moveTo(mapX(xAxisData[0]), mapY(-yAxisData2[0])); + for (int i = 0; i < xAxisData.length; i++) { + // line tracing through points + g2d.lineTo(mapX(xAxisData[i]), mapY(-yAxisData2[i])); + } + g2d.stroke(); + } + + + if (ticsY.length > 1) { + // border and fill + g2d.setLineWidth(0.5); + g2d.setStroke(Paint.valueOf("BLACK")); + g2d.strokeRect( + mapX(minX), + mapY(ticsY[ticsY.length - 1].doubleValue()), + graphWidth, + StrictMath.abs(mapY(ticsY[ticsY.length - 1].doubleValue()) - mapY(ticsY[0].doubleValue()))); + + g2d.setFill(Paint.valueOf("BLACK")); + + // ticsY + float verticalTextShift = 3.2f; + g2d.setFont(Font.font("SansSerif", 10)); + if (ticsY != null) { + for (int i = 0; i < ticsY.length; i++) { + g2d.strokeLine( + mapX(minX), mapY(ticsY[i].doubleValue()), mapX(maxX), mapY(ticsY[i].doubleValue())); + + // left side + text.setText(ticsY[i].toString()); + textWidth = (int) text.getLayoutBounds().getWidth(); + g2d.fillText(text.getText(),// + (float) mapX(minX) - textWidth + 5f, + (float) mapY(ticsY[i].doubleValue()) + verticalTextShift); + + } + // ticsX + if (ticsX != null) { + for (int i = 0; i < ticsX.length - 1; i++) { + try { + g2d.strokeLine( + mapX(ticsX[i].doubleValue()), + mapY(ticsY[0].doubleValue()), + mapX(ticsX[i].doubleValue()), + mapY(ticsY[0].doubleValue()) + 5); + + // bottom + String xText = ticsX[i].toPlainString(); + g2d.fillText(xText, + (float) mapX(ticsX[i].doubleValue()) - 5f, + (float) mapY(ticsY[0].doubleValue()) + 15); + + } catch (Exception e) { + } + } + } + } + } + } +} \ No newline at end of file diff --git a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterPlot.java b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterPlot.java index 46398ff0..6a326113 100644 --- a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterPlot.java +++ b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/BasicScatterPlot.java @@ -72,7 +72,7 @@ public void paint(GraphicsContext g2d) { g2d.fillText(intensityLinePlotBuilder.getTitle(), leftMargin + 25, 15); g2d.setLineWidth(0.5); - // new line graph + // scatter plot g2d.setStroke(Paint.valueOf("Black")); for (int i = 0; i < xAxisData.length; i++) { g2d.strokeOval(mapX(xAxisData[i]) - 2f, mapY(yAxisData[i]) -2f, 4f, 4f); diff --git a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotBuildersTask.java b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotBuildersTask.java index f4546b1b..a901c615 100644 --- a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotBuildersTask.java +++ b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotBuildersTask.java @@ -37,7 +37,8 @@ public class RJMCMCPlotBuildersTask extends Task implements LoggingCallb private AbstractPlotBuilder convergeRatioLineBuilder; - private AbstractPlotBuilder ObserveDataLineBuilder; + private AbstractPlotBuilder observedDataLineBuilder; + private AbstractPlotBuilder residualDataLineBuilder; public RJMCMCPlotBuildersTask(Path dataFile) { this.dataFile = dataFile; @@ -67,8 +68,12 @@ public AbstractPlotBuilder getConvergeRatioLineBuilder() { return convergeRatioLineBuilder; } - public AbstractPlotBuilder getObserveDataLineBuilder() { - return ObserveDataLineBuilder; + public AbstractPlotBuilder getObservedDataLineBuilder() { + return observedDataLineBuilder; + } + + public AbstractPlotBuilder getResidualDataLineBuilder() { + return residualDataLineBuilder; } @Override @@ -82,7 +87,8 @@ protected String call() throws Exception { convergeRatioLineBuilder = plots[5]; - ObserveDataLineBuilder = plots[6]; + observedDataLineBuilder = plots[6]; + residualDataLineBuilder = plots[7]; return "DONE"; } diff --git a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotsController.java b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotsController.java index 47a72d87..9fa84cc3 100644 --- a/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotsController.java +++ b/TripoliApp/src/main/java/org/cirdles/tripoli/gui/dataViews/plots/plotsControllers/RJMCMCPlots/RJMCMCPlotsController.java @@ -1,7 +1,5 @@ package org.cirdles.tripoli.gui.dataViews.plots.plotsControllers.RJMCMCPlots; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.*; @@ -11,12 +9,10 @@ import javafx.scene.shape.Rectangle; import org.cirdles.commons.util.ResourceExtractor; import org.cirdles.tripoli.Tripoli; -import org.cirdles.tripoli.gui.dataViews.plots.AbstractDataView; -import org.cirdles.tripoli.gui.dataViews.plots.BasicScatterPlot; -import org.cirdles.tripoli.gui.dataViews.plots.HistogramPlot; -import org.cirdles.tripoli.gui.dataViews.plots.BasicLinePlot; +import org.cirdles.tripoli.gui.dataViews.plots.*; import org.cirdles.tripoli.visualizationUtilities.AbstractPlotBuilder; import org.cirdles.tripoli.visualizationUtilities.histograms.HistogramBuilder; +import org.cirdles.tripoli.visualizationUtilities.linePlots.ComboPlotBuilder; import org.cirdles.tripoli.visualizationUtilities.linePlots.LinePlotBuilder; import java.io.IOException; @@ -112,7 +108,8 @@ public void processDataFileAndShowPlotsOfRJMCMC() throws IOException { AbstractPlotBuilder convergeRatioPlotBuilder = ((RJMCMCPlotBuildersTask) service.getPlotBuildersTask()).getConvergeRatioLineBuilder(); - AbstractPlotBuilder observedDataPlotBuilder = ((RJMCMCPlotBuildersTask) service.getPlotBuildersTask()).getObserveDataLineBuilder(); + AbstractPlotBuilder observedDataPlotBuilder = ((RJMCMCPlotBuildersTask) service.getPlotBuildersTask()).getObservedDataLineBuilder(); + AbstractPlotBuilder residualDataPlotBuilder = ((RJMCMCPlotBuildersTask) service.getPlotBuildersTask()).getResidualDataLineBuilder(); AbstractDataView ratiosHistogramPlot = new HistogramPlot( new Rectangle(ensembleGridPane.getWidth(), @@ -145,58 +142,61 @@ public void processDataFileAndShowPlotsOfRJMCMC() throws IOException { convergeRatioScrollPane.getHeight()), (LinePlotBuilder) convergeRatioPlotBuilder); - AbstractDataView observedDataLinePlot = new BasicScatterPlot( + AbstractDataView observedDataLinePlot = new BasicScatterAndLinePlot( new Rectangle(dataFitGridPane.getWidth(), dataFitGridPane.getHeight() / dataFitGridPane.getRowCount()), - (LinePlotBuilder) observedDataPlotBuilder); - - - plotTabPane.widthProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Number oldValue, Number newValue) { - if (newValue.intValue() > 100) { - double newWidth = newValue.intValue() - ensembleLegendTextBox.getWidth(); - ratiosHistogramPlot.setMyWidth(newWidth); - ratiosHistogramPlot.repaint(); - baselineHistogramPlot.setMyWidth(newWidth / ensembleGridPane.getColumnCount()); - baselineHistogramPlot.repaint(); - dalyFaradayHistogramPlot.setMyWidth(newWidth / ensembleGridPane.getColumnCount()); - dalyFaradayHistogramPlot.repaint(); - intensityLinePlot.setMyWidth(newWidth); - intensityLinePlot.repaint(); - signalNoiseHistogramPlot.setMyWidth(newWidth); - signalNoiseHistogramPlot.repaint(); - - convergeRatioLinePlot.setMyWidth(newValue.intValue()); - convergeRatioLinePlot.repaint(); - - observedDataLinePlot.setMyWidth(newWidth); - observedDataLinePlot.repaint(); - } + (ComboPlotBuilder) observedDataPlotBuilder); + + AbstractDataView residualDataLinePlot = new BasicScatterAndLinePlot( + new Rectangle(dataFitGridPane.getWidth(), + dataFitGridPane.getHeight() / dataFitGridPane.getRowCount()), + (ComboPlotBuilder) residualDataPlotBuilder); + + + plotTabPane.widthProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.intValue() > 100) { + double newWidth = newValue.intValue() - ensembleLegendTextBox.getWidth(); + ratiosHistogramPlot.setMyWidth(newWidth); + ratiosHistogramPlot.repaint(); + baselineHistogramPlot.setMyWidth(newWidth / ensembleGridPane.getColumnCount()); + baselineHistogramPlot.repaint(); + dalyFaradayHistogramPlot.setMyWidth(newWidth / ensembleGridPane.getColumnCount()); + dalyFaradayHistogramPlot.repaint(); + intensityLinePlot.setMyWidth(newWidth); + intensityLinePlot.repaint(); + signalNoiseHistogramPlot.setMyWidth(newWidth); + signalNoiseHistogramPlot.repaint(); + + convergeRatioLinePlot.setMyWidth(newValue.intValue()); + convergeRatioLinePlot.repaint(); + + observedDataLinePlot.setMyWidth(newWidth); + observedDataLinePlot.repaint(); + residualDataLinePlot.setMyWidth(newWidth); + residualDataLinePlot.repaint(); } }); - plotTabPane.heightProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Number oldValue, Number newValue) { - if (newValue.intValue() > 100) { - ratiosHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); - ratiosHistogramPlot.repaint(); - baselineHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); - baselineHistogramPlot.repaint(); - dalyFaradayHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); - dalyFaradayHistogramPlot.repaint(); - intensityLinePlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); - intensityLinePlot.repaint(); - signalNoiseHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); - signalNoiseHistogramPlot.repaint(); - - convergeRatioLinePlot.setMyHeight(newValue.intValue()); - convergeRatioLinePlot.repaint(); - - observedDataLinePlot.setMyHeight(newValue.intValue()); - observedDataLinePlot.repaint(); - } + plotTabPane.heightProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.intValue() > 100) { + ratiosHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); + ratiosHistogramPlot.repaint(); + baselineHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); + baselineHistogramPlot.repaint(); + dalyFaradayHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); + dalyFaradayHistogramPlot.repaint(); + intensityLinePlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); + intensityLinePlot.repaint(); + signalNoiseHistogramPlot.setMyHeight(newValue.intValue() / ensembleGridPane.getRowCount() - 5); + signalNoiseHistogramPlot.repaint(); + + convergeRatioLinePlot.setMyHeight(newValue.intValue()); + convergeRatioLinePlot.repaint(); + + observedDataLinePlot.setMyHeight(newValue.intValue() / dataFitGridPane.getRowCount() - 5); + observedDataLinePlot.repaint(); + residualDataLinePlot.setMyHeight(newValue.intValue() / dataFitGridPane.getRowCount() - 5); + residualDataLinePlot.repaint(); } }); @@ -216,6 +216,8 @@ public void changed(ObservableValue observable, Number oldValu observedDataLinePlot.preparePanel(); dataFitGridPane.add(observedDataLinePlot, 0,0); + residualDataLinePlot.preparePanel(); + dataFitGridPane.add(residualDataLinePlot, 0,1); }); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataOutputModels/rjmcmc/DataModelDriverExperiment.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataOutputModels/rjmcmc/DataModelDriverExperiment.java index ce0c2833..5d007586 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataOutputModels/rjmcmc/DataModelDriverExperiment.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataOutputModels/rjmcmc/DataModelDriverExperiment.java @@ -27,6 +27,7 @@ import org.cirdles.tripoli.utilities.stateUtilities.TripoliSerializer; import org.cirdles.tripoli.visualizationUtilities.AbstractPlotBuilder; import org.cirdles.tripoli.visualizationUtilities.histograms.HistogramBuilder; +import org.cirdles.tripoli.visualizationUtilities.linePlots.ComboPlotBuilder; import org.cirdles.tripoli.visualizationUtilities.linePlots.LinePlotBuilder; import java.io.IOException; @@ -48,7 +49,7 @@ */ public class DataModelDriverExperiment { - private static final boolean doFullProcessing = true; + private static final boolean doFullProcessing = false; public static AbstractPlotBuilder[] driveModelTest(Path dataFilePath, LoggingCallbackInterface loggingCallback) throws IOException { @@ -236,7 +237,7 @@ static AbstractPlotBuilder[] applyInversionWithRJMCMC(MassSpecOutputDataRecord m // only using first block - IntensityPerBlock is calculated already in initializer //Matrix Intensity; for (int blockIndex = 0; blockIndex < 1; blockIndex++) { - // Intensity = massSpecOutputDataRecord.firstBlockInterpolations().times(dataModelInit.blockIntensities()); + // Intensity = massSpecOutputDataRecord.firstBlockInterpolations().times(dataModelInit.blockIntensities()); for (int isotopeIndex = 0; isotopeIndex < massSpecOutputDataRecord.isotopeCount(); isotopeIndex++) { for (int row = 0; row < massSpecOutputDataRecord.rawDataColumn().getRowDimension(); row++) { @@ -851,9 +852,8 @@ private static AbstractPlotBuilder[] analysisAndPlotting( } - // visualization - Ensembles tab - AbstractPlotBuilder[] plotBuilders = new AbstractPlotBuilder[7]; + AbstractPlotBuilder[] plotBuilders = new AbstractPlotBuilder[10]; plotBuilders[0] = HistogramBuilder.initializeHistogram(ensembleRatios, 50, "Histogram of ratios"); plotBuilders[1] = HistogramBuilder.initializeHistogram(true, ensembleBaselines, 50, "Histogram of baseline"); plotBuilders[2] = HistogramBuilder.initializeHistogram(ensembleDalyFaradayGain, 50, "Histogram of Daly/Faraday Gain"); @@ -894,12 +894,12 @@ private static AbstractPlotBuilder[] analysisAndPlotting( // only first block for now // todo: this is duplicated code from above in part + double[] data = lastDataModelInit.dataArray().getColumnPackedCopy(); + double[] dataWithNoBaseline = new double[lastDataModelInit.dataArray().getRowDimension()]; EnsembleRecord lastModelRecord = ensembleRecordsList.get(ensembleRecordsList.size() - 1); for (int blockIndex = 0; blockIndex < 1; blockIndex++) { Matrix[] intensity = new Matrix[1]; intensity[0] = lastDataModelInit.intensityPerBlock()[0]; - Matrix data = (Matrix) lastDataModelInit.dataArray().clone(); - Matrix dataWithNoBaseline = new Matrix(lastDataModelInit.dataArray().getRowDimension(), 1); for (int isotopeIndex = 0; isotopeIndex < massSpecOutputDataRecord.isotopeCount(); isotopeIndex++) { for (int row = 0; row < massSpecOutputDataRecord.rawDataColumn().getRowDimension(); row++) { if ((massSpecOutputDataRecord.isotopeFlagsForRawDataColumn().get(row, isotopeIndex) == 1) @@ -908,8 +908,8 @@ private static AbstractPlotBuilder[] analysisAndPlotting( double calcValue = exp(lastModelRecord.logRatios().get(isotopeIndex, 0)) * intensity[0].get((int) massSpecOutputDataRecord.timeIndColumn().get(row, 0) - 1, 0); - data.set(row, 0, calcValue); - dataWithNoBaseline.set(row, 0, calcValue); + data[row] = calcValue; + dataWithNoBaseline[row] = calcValue; } if ((massSpecOutputDataRecord.isotopeFlagsForRawDataColumn().get(row, isotopeIndex) == 1) && (massSpecOutputDataRecord.axialFlagsForRawDataColumn().get(row, 0) == 0) @@ -917,24 +917,42 @@ private static AbstractPlotBuilder[] analysisAndPlotting( double calcValue = exp(lastModelRecord.logRatios().get(isotopeIndex, 0)) / lastModelRecord.dfGain() * intensity[0].get((int) massSpecOutputDataRecord.timeIndColumn().get(row, 0) - 1, 0); - dataWithNoBaseline.set(row, 0, calcValue); - data.set(row, 0, - calcValue + lastModelRecord.baseLine().get((int) massSpecOutputDataRecord.detectorIndicesForRawDataColumn().get(row, 0) - 1, 0)); + data[row] = calcValue + lastModelRecord.baseLine().get((int) massSpecOutputDataRecord.detectorIndicesForRawDataColumn().get(row, 0) - 1, 0); + dataWithNoBaseline[row] = calcValue; } } } } - int step = 10; - double [] dataCounts = massSpecOutputDataRecord.rawDataColumn().getColumnPackedCopy(); - double[] xDataIndex = new double[dataCounts.length / step]; - double[] yDataCounts = new double[dataCounts.length / step]; + // Dsig = sqrt(x.sig(d0.det_vec).^2 + x.sig(end).*dnobl); % New data covar vector + double[] xSig = lastModelRecord.signalNoise.getColumnPackedCopy(); + double[] detectorIndicesForRawDataColumn = massSpecOutputDataRecord.detectorIndicesForRawDataColumn().getColumnPackedCopy(); + double[] dataCountsModelOneSigma = new double[detectorIndicesForRawDataColumn.length]; + for (int row = 0; row < detectorIndicesForRawDataColumn.length; row++) { + dataCountsModelOneSigma[row] + = StrictMath.sqrt(StrictMath.pow(xSig[(int) detectorIndicesForRawDataColumn[row] - 1], 2) + + xSig[xSig.length - 1] * dataWithNoBaseline[row]); + } - for (int i = 0; i < dataCounts.length / step; i++) { - xDataIndex[i] = i * step; - yDataCounts[i] = dataCounts[i * step]; + int plottingStep = 10; + double[] dataOriginalCounts = massSpecOutputDataRecord.rawDataColumn().getColumnPackedCopy(); + double[] xDataIndex = new double[dataOriginalCounts.length / plottingStep]; + double[] yDataCounts = new double[dataOriginalCounts.length / plottingStep]; + double[] yDataModelCounts = new double[dataOriginalCounts.length / plottingStep]; + + double[] yDataResiduals = new double[dataOriginalCounts.length / plottingStep]; + double[] yDataSigmas = new double[dataOriginalCounts.length / plottingStep]; + + for (int i = 0; i < dataOriginalCounts.length / plottingStep; i++) { + xDataIndex[i] = i * plottingStep; + yDataCounts[i] = dataOriginalCounts[i * plottingStep]; + yDataModelCounts[i] = data[i * plottingStep]; + yDataResiduals[i] = dataOriginalCounts[i * plottingStep] - data[i * plottingStep]; + yDataSigmas[i] = dataCountsModelOneSigma[i * plottingStep]; } - plotBuilders[6] = LinePlotBuilder.initializeLinePlot(xDataIndex, yDataCounts, "Observed Data"); + plotBuilders[6] = ComboPlotBuilder.initializeLinePlot(xDataIndex, yDataCounts, yDataModelCounts, "Observed Data"); + + plotBuilders[7] = ComboPlotBuilder.initializeLinePlotWithOneSigma(xDataIndex, yDataResiduals, yDataSigmas, "Residual Data"); // todo: missing additional elements of signalNoise (i.e., 0,11,11) System.err.println(logRatioMean + " " + logRatioStdDev); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/visualizationUtilities/linePlots/ComboPlotBuilder.java b/TripoliCore/src/main/java/org/cirdles/tripoli/visualizationUtilities/linePlots/ComboPlotBuilder.java new file mode 100644 index 00000000..72bc9cf7 --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/visualizationUtilities/linePlots/ComboPlotBuilder.java @@ -0,0 +1,59 @@ +/* + * Copyright 2022 James Bowring, Noah McLean, Scott Burdick, and CIRDLES.org. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cirdles.tripoli.visualizationUtilities.linePlots; + +import org.cirdles.tripoli.visualizationUtilities.AbstractPlotBuilder; + +public class ComboPlotBuilder extends AbstractPlotBuilder { + + private final double[] xData; + private final double[] yData; + private final double[] yData2; + private boolean yData2OneSigma; + + protected ComboPlotBuilder(double[] xData, double[] yData, double[] yData2, boolean yData2OneSigma, String title ) { + super(title); + this.xData = xData; + this.yData = yData; + this.yData2 = yData2; + this.yData2OneSigma = yData2OneSigma; + } + + public static ComboPlotBuilder initializeLinePlot(double[] xData, double[] yData, double[] yData2, String title) { + return new ComboPlotBuilder(xData, yData, yData2, false, title); + } + + public static ComboPlotBuilder initializeLinePlotWithOneSigma(double[] xData, double[] yData, double[] yData2, String title) { + return new ComboPlotBuilder(xData, yData, yData2, true, title); + } + + public double[] getyData() { + return yData; + } + + public double[] getxData() { + return xData; + } + + public double[] getyData2() { + return yData2; + } + + public boolean isyData2OneSigma() { + return yData2OneSigma; + } +} \ No newline at end of file