/* * FitFunctionsOnDownHoleRatioDataView.java * * Copyright 2006-2018 James F. Bowring, CIRDLES.org, and Earth-Time.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.earthtime.Tripoli.dataViews.simpleViews.usedByReflection; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import javax.swing.JLayeredPane; import org.earthtime.Tripoli.dataModels.DataModelInterface; import org.earthtime.Tripoli.dataModels.MaskingSingleton; import org.earthtime.Tripoli.dataModels.RawRatioDataModel; import org.earthtime.Tripoli.dataViews.AbstractRawDataView; import org.earthtime.Tripoli.dataViews.simpleViews.FitFunctionDataInterface; import org.earthtime.Tripoli.fractions.TripoliFraction; import org.earthtime.dataDictionaries.DataPresentationModeEnum; import org.earthtime.dataDictionaries.IncludedTypeEnum; import org.earthtime.utilities.TicGeneratorForAxes; /** * * @author James F. Bowring */ public class FitFunctionsOnDownHoleRatioDataView extends AbstractRawDataView implements FitFunctionDataInterface { /** * */ public static int DEFAULT_WIDTH_OF_PANE = 128; private double[] fittedFunctionValues; private boolean showFittedFunction; /** * * @param sampleSessionDataView * @param tripoliFraction * @param rawRatioDataModel * @param bounds * @param invokeMouseListener */ public FitFunctionsOnDownHoleRatioDataView(// JLayeredPane sampleSessionDataView, // TripoliFraction tripoliFraction,// DataModelInterface rawRatioDataModel,// Rectangle bounds,// boolean invokeMouseListener) { super(sampleSessionDataView, tripoliFraction, bounds, invokeMouseListener, true); this.rawRatioDataModel = rawRatioDataModel; this.fittedFunctionValues = null; this.showFittedFunction = false; this.standardValue = rawRatioDataModel.getStandardValue(); this.dataPresentationMode = DataPresentationModeEnum.LOGRATIO; } /** * * @param g2d */ @Override public void paint(Graphics2D g2d) { super.paint(g2d); if (myOnPeakData != null) { // feb 2013 change of approach: instead of red lines, just bypass the point altogether // find first active point boolean[] dataActiveMap = rawRatioDataModel.getDataActiveMap(); int firstActiveIndex = 0; for (int i = 0; i < dataActiveMap.length; i++) { if (dataActiveMap[i]) { break; } else { firstActiveIndex++; } } // draw connecting line if possible if (firstActiveIndex < dataActiveMap.length) { Shape connectingLine = new Path2D.Double(); g2d.setPaint(tripoliFraction.isIncluded() ? getPaintColor() : EXCLUDED_COLOR); g2d.setStroke(new BasicStroke(0.75f)); ((Path2D) connectingLine).moveTo(// mapX(myOnPeakNormalizedAquireTimes[firstActiveIndex]), // mapY(myOnPeakData[0])); for (int i = firstActiveIndex + 1; i < myOnPeakNormalizedAquireTimes.length; i++) { if (dataActiveMap[i]) { ((Path2D) connectingLine).lineTo( // mapX(myOnPeakNormalizedAquireTimes[i]), mapY(myOnPeakData[i - firstActiveIndex])); } } g2d.draw(connectingLine); } // data points g2d.setStroke(new BasicStroke(1.5f)); for (int i = firstActiveIndex; i < myOnPeakNormalizedAquireTimes.length; i++) { // nov 2014 to handle */Pb204 Shape dataPoint = null; // // logs cant be nan and ratios or alphas cant be neg // if (!rawRatioDataModel.isForceMeanForCommonLeadRatios() // // && // // Double.isNaN(myOnPeakData[i])) { // Font specialFont = new Font("Courier New", Font.PLAIN, 10); // GlyphVector vect = specialFont.createGlyphVector(g2d.getFontRenderContext(), "+"); // dataPoint = vect.getOutline((float) mapX(myOnPeakNormalizedAquireTimes[i]) - 3, (float) mapY(minY)); // } else { //downhole standards have no common lead dataPoint = new java.awt.geom.Ellipse2D.Double( // mapX(myOnPeakNormalizedAquireTimes[i]), mapY(myOnPeakData[i - firstActiveIndex]), 1, 1); // } g2d.setPaint(determineDataColor(i, getPaintColor())); g2d.draw(dataPoint); } if (showFittedFunction) { // draw fittedFunctionAverageLine for intercept case Shape fittedFunctionAverageLine = new Path2D.Double(); g2d.setPaint(Color.RED); g2d.setStroke(new BasicStroke(3.0f)); ((Path2D) fittedFunctionAverageLine).moveTo(// mapX(myOnPeakNormalizedAquireTimes[0]), // mapY(fittedFunctionValues[0])); for (int i = firstActiveIndex; i < myOnPeakNormalizedAquireTimes.length; i++) { ((Path2D) fittedFunctionAverageLine).lineTo( // mapX(myOnPeakNormalizedAquireTimes[i]), mapY(fittedFunctionValues[i - firstActiveIndex])); } g2d.draw(fittedFunctionAverageLine); } // draw masking shades boolean[] maskingArray = MaskingSingleton.getInstance().getMaskingArray(); //left int leftEdgeIndex = -1; boolean leftEdgeFound = false; int rightEdgeIndex = maskingArray.length; for (int i = 0; i < maskingArray.length; i++) { if ((!leftEdgeFound) && (!maskingArray[i])) { leftEdgeIndex = i; } else { leftEdgeFound = true; } if (leftEdgeFound && !maskingArray[i]) { rightEdgeIndex = i; break; } } Composite originalComposite = g2d.getComposite(); g2d.setPaint(Color.gray); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); if (leftEdgeIndex > -1) { Shape leftShade = new Rectangle2D.Double( // mapX(minX), // -1, mapX((double) myOnPeakNormalizedAquireTimes[leftEdgeIndex] + (double) (myOnPeakNormalizedAquireTimes[1] - myOnPeakNormalizedAquireTimes[0]) / 2.0),// getHeight() + 1); g2d.fill(leftShade); } if (rightEdgeIndex < maskingArray.length) { Shape rightShade = new Rectangle2D.Double( // mapX((double) myOnPeakNormalizedAquireTimes[rightEdgeIndex] - (double) (myOnPeakNormalizedAquireTimes[1] - myOnPeakNormalizedAquireTimes[0]) / 2.0),// -1, mapX(maxX), // getHeight() + 1); g2d.fill(rightShade); } g2d.setComposite(originalComposite); } else { g2d.drawString("BELOW DETECTION", 25, 25); } } /** * */ @Override public void updateFittedData(boolean doReScale) { if (!notShownDueToBelowDetectionFlag) { fittedFunctionValues = ((RawRatioDataModel) rawRatioDataModel).getDownHoleFitFunctionLogValues().clone(); // choose data and walk data and get min and max for axes myOnPeakData = ((RawRatioDataModel) rawRatioDataModel).getLogDifferencesFromWeightedMean().clone(); if (doReScale) { // X-axis lays out time evenly spaced minX = myOnPeakNormalizedAquireTimes[0]; maxX = myOnPeakNormalizedAquireTimes[myOnPeakNormalizedAquireTimes.length - 1]; // adjust margins for unknowns double xMarginStretch = TicGeneratorForAxes.generateMarginAdjustment(minX, maxX, 0.05); minX -= xMarginStretch; maxX += xMarginStretch; // Y-axis is ratios minY = Double.MAX_VALUE; maxY = -Double.MAX_VALUE; // find min and max y boolean[] myDataActiveMap = rawRatioDataModel.getDataActiveMap(); boolean showAll = showIncludedDataPoints.equals(IncludedTypeEnum.ALL); // rework logic April 2016 for (int i = 0; i < myOnPeakData.length; i++) { if (!!Double.isFinite(myOnPeakData[i]) && (showAll || myDataActiveMap[i])) { minY = Math.min(minY, myOnPeakData[i]); maxY = Math.max(maxY, myOnPeakData[i]); } minY = Math.min(minY, fittedFunctionValues[i]); maxY = Math.max(maxY, fittedFunctionValues[i]); } double yMarginStretch = TicGeneratorForAxes.generateMarginAdjustment(minY, maxY, 12.0 / this.getHeight());// 0.05 ); minY -= yMarginStretch; maxY += yMarginStretch; } } } /** * * @param doReScale the value of doReScale * @param inLiveMode the value of inLiveMode */ @Override public void preparePanel(boolean doReScale, boolean inLiveMode) { this.removeAll(); if (doReScale) { setDisplayOffsetY(0.0); setDisplayOffsetX(0.0); } // normalize aquireTimes myOnPeakNormalizedAquireTimes = rawRatioDataModel.getNormalizedOnPeakAquireTimes(); notShownDueToBelowDetectionFlag = rawRatioDataModel.isBelowDetection(); updateFittedData(doReScale); } /** * * @return */ @Override public DataModelInterface getDataModel() { return rawRatioDataModel; } /** * @param showFittedFunction the showFittedFunction to set */ @Override public void setShowFittedFunction(boolean showFittedFunction) { this.showFittedFunction = showFittedFunction; } /** * * @return */ @Override public boolean amShowingUnknownFraction() { return !tripoliFraction.isStandard(); } }