From d03cb5b9d1955fe544808f79834c85360fbbad06 Mon Sep 17 00:00:00 2001 From: Jim Bowring Date: Fri, 5 Apr 2024 09:26:47 -0400 Subject: [PATCH 1/4] Updated web pages --- docs/_config.yml | 2 +- docs/_includes/themes/twitter/default.html | 5 +++-- docs/references.md | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 docs/references.md diff --git a/docs/_config.yml b/docs/_config.yml index e184f545..623cb832 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -31,7 +31,7 @@ JB: # also use ruby on mac (rom) to keep updated # need to change Ruby version: chruby ruby-2.7.5 - BASE_PATH: /Tripoli + #BASE_PATH: /Tripoli version: 0.3.0 # All links will be namespaced by BASE_PATH if defined. diff --git a/docs/_includes/themes/twitter/default.html b/docs/_includes/themes/twitter/default.html index 4022bfd8..176631af 100644 --- a/docs/_includes/themes/twitter/default.html +++ b/docs/_includes/themes/twitter/default.html @@ -36,11 +36,12 @@ {{ site.title }} diff --git a/docs/references.md b/docs/references.md new file mode 100644 index 00000000..7a978780 --- /dev/null +++ b/docs/references.md @@ -0,0 +1,8 @@ +--- +layout: page +title: Tripoli References +description: Tripoli references used +--- + +Adaptive Metropolis by Gareth Roberts 2008 + From 44e83dd939ac002675e8f7a809ee10f2bf60d32a Mon Sep 17 00:00:00 2001 From: Jim Bowring Date: Fri, 5 Apr 2024 09:29:03 -0400 Subject: [PATCH 2/4] Updated web pages --- docs/_config.yml | 2 +- docs/references.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index 623cb832..e184f545 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -31,7 +31,7 @@ JB: # also use ruby on mac (rom) to keep updated # need to change Ruby version: chruby ruby-2.7.5 - #BASE_PATH: /Tripoli + BASE_PATH: /Tripoli version: 0.3.0 # All links will be namespaced by BASE_PATH if defined. diff --git a/docs/references.md b/docs/references.md index 7a978780..a782d663 100644 --- a/docs/references.md +++ b/docs/references.md @@ -1,6 +1,6 @@ --- layout: page -title: Tripoli References +title: Tripoli references description: Tripoli references used --- From 7bac810f1449e8efc9fdb18f7343321a7f6c361f Mon Sep 17 00:00:00 2001 From: Jim Bowring Date: Tue, 16 Apr 2024 14:08:44 -0400 Subject: [PATCH 3/4] Refined reading of aborted xls files --- TripoliCore/build.gradle.kts | 6 +- TripoliCore/src/main/java/module-info.java | 2 + .../org/cirdles/tripoli/DataDictionary.java | 109 +++++++++ .../tripoli/constants/TripoliConstants.java | 1 + .../tripoli/sessions/analysis/Analysis.java | 10 +- .../AllBlockInitForDataLiteOne.java | 4 +- .../phoenix/PhoenixMassSpec.java | 30 ++- .../analysis/methods/AnalysisMethod.java | 13 +- .../outputs/etRedux/ETReduxFraction.java | 218 ++++++++++++++++++ .../outputs/etRedux/MeasuredRatioModel.java | 136 +++++++++++ .../xml/ETReduxFractionXMLConverter.java | 200 ++++++++++++++++ .../xml/MeasuredRatioModelXMLConverter.java | 131 +++++++++++ .../utilities/xml/XMLSerializerInterface.java | 104 +++++++++ .../tripoli/valueModels/ValueModel.java | 18 +- .../tripoli/schema/UPbReduxInputXMLSchema.xsd | 69 ++++++ .../tripoli/schema/listOfResourceFiles.txt | 3 +- .../outputs/etRedux/ETReduxFractionTest.java | 34 +++ .../etRedux/MeasuredRatioModelTest.java | 33 +++ .../src/main/kotlin/common-build.gradle.kts | 2 +- 19 files changed, 1095 insertions(+), 28 deletions(-) create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/DataDictionary.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFraction.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModel.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/ETReduxFractionXMLConverter.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/MeasuredRatioModelXMLConverter.java create mode 100644 TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/XMLSerializerInterface.java create mode 100644 TripoliCore/src/main/resources/org/cirdles/tripoli/schema/UPbReduxInputXMLSchema.xsd create mode 100644 TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFractionTest.java create mode 100644 TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModelTest.java diff --git a/TripoliCore/build.gradle.kts b/TripoliCore/build.gradle.kts index 62e5f69f..d53d693c 100644 --- a/TripoliCore/build.gradle.kts +++ b/TripoliCore/build.gradle.kts @@ -72,6 +72,8 @@ dependencies { // https://mvnrepository.com/artifact/org.jblas/jblas implementation("org.jblas:jblas:1.2.5") + // https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream + implementation("com.thoughtworks.xstream:xstream:1.4.20") testImplementation("com.github.cirdles:commons:bc38781605") @@ -84,7 +86,6 @@ tasks.test { useJUnitPlatform() } - val timestamp = { SimpleDateFormat("dd MMMM yyyy").format(Date()) } @@ -92,7 +93,6 @@ repositories { mavenCentral() } - extraJavaModuleInfo { failOnMissingModuleInfo.set(false) automaticModule("commons-bc38781605.jar", "commons.bc38781605") @@ -105,7 +105,7 @@ extraJavaModuleInfo { automaticModule("org.jblas:jblas", "jblas") - //automaticModule("javax.xml.bind:jaxb-api", "jaxb.api")//javax.xml.bind:jaxb-api:2.3.1 + automaticModule("com.thoughtworks.xstream:xstream", "xstream")//javax.xml.bind:jaxb-api:2.3.1 } diff --git a/TripoliCore/src/main/java/module-info.java b/TripoliCore/src/main/java/module-info.java index 858878a9..e7edecc5 100644 --- a/TripoliCore/src/main/java/module-info.java +++ b/TripoliCore/src/main/java/module-info.java @@ -26,6 +26,8 @@ requires jakarta.xml.bind; requires java.xml.bind; requires jblas; + requires xstream; + requires java.logging; exports org.cirdles.tripoli; diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/DataDictionary.java b/TripoliCore/src/main/java/org/cirdles/tripoli/DataDictionary.java new file mode 100644 index 00000000..5cb2264c --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/DataDictionary.java @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright 2004-2024 James F. Bowring and www.Earth-Time.org + * Ported from OGTripoli + * + * 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; + +public enum DataDictionary { + ; + public static String[] EarthTimeBariumPhosphateICIsotopeNames = new String[]{ + "pct130Ba_BaPO2", + "pct132Ba_BaPO2", + "pct134Ba_BaPO2", + "pct135Ba_BaPO2", + "pct136Ba_BaPO2", + "pct137Ba_BaPO2", + "pct138Ba_BaPO2", + "pct16O_BaPO2", + "pct17O_BaPO2", + "pct18O_BaPO2" + }; + + public static String[] EarthTimeThalliumICIsotopeNames = new String[]{ + "pct203Tl_Tl", + "pct205Tl_Tl" + }; + + public static String[] EarthTimeTracerRatioNames = new String[]{ + "206_204", + "207_206", + "206_208", + "206_205", + "207_205", + "208_205", + "202_205", + "238_235", + "233_235", + "233_236", + "235_205"}; + + public static String[] UPbReduxMeasuredRatioNames = new String[]{ + "206_204", + "207_204", + "208_204", + "206_207", + "206_208", + "204_205", + "206_205", + "207_205", + "208_205", + "202_205", + "238_236", //jan 2011 + "233_236", + "238_235", + "233_235", + "238_233"}; + public static String[] isotopeNames = new String[] + {"Pb205", + "U235"}; + public static String[] TracerTypes = new String[] + {"mixed 205-235", + "mixed 205-233-235", + "mixed 208-235", + "mixed 205-233-236", + "mixed 202-205-233-235", + "mixed 202-205-233-236", + "mixed 205-233-235-230Th"}; + + public static String getEarthTimeBariumPhosphateICIsotopeNames(int index) { + return EarthTimeBariumPhosphateICIsotopeNames[index]; + } + + public static String getEarthTimeThalliumICIsotopeNames(int index) { + return EarthTimeThalliumICIsotopeNames[index]; + } + + public static String getTracerRatioName(int index) { + return "r" + EarthTimeTracerRatioNames[index] + "t"; + } + + public static String getTracerIsotopeConcName(int index) { + return "conc" + isotopeNames[index] + "t"; + } + + public static String getMeasuredRatioName(int index) { + return "r" + UPbReduxMeasuredRatioNames[index] + "m"; + } + + public static String getElementNameOfRatio(String name) { + if (name.substring(1, 1).equals("0")) + return "Pb"; + else + return "U"; + } + +} + diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/constants/TripoliConstants.java b/TripoliCore/src/main/java/org/cirdles/tripoli/constants/TripoliConstants.java index 1e93e497..81a162fd 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/constants/TripoliConstants.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/constants/TripoliConstants.java @@ -52,6 +52,7 @@ public enum TripoliConstants { public static final String SPACES_100 = CharBuffer.allocate(100).toString().replace('\0', ' '); + public static final String SPACES_150 = CharBuffer.allocate(150).toString().replace('\0', ' '); public static final String MISSING_STRING_FIELD = "MISSING"; diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java index 6374ff60..367ca844 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java @@ -252,6 +252,8 @@ public void extractMassSpecDataFromPath(Path dataFilePath) analysisMethod = AnalysisMethod.createAnalysisMethodFromCase1(massSpecExtractedData); initializeBlockProcessing(); } + + analysisName = dataFilePath.toFile().getName(); } public void initializeBlockProcessing() { @@ -394,7 +396,7 @@ public AllBlockInitForMCMC.PlottingData assemblePostProcessPlottingData() { public final String prettyPrintAnalysisSummary() { return analysisName + - SPACES_100.substring(0, 40 - analysisName.length()) + + SPACES_150.substring(0, 100 - analysisName.length()) + (null == analysisMethod ? "NO Method" : analysisMethod.prettyPrintMethodSummary(false)); } @@ -427,8 +429,10 @@ public final String prettyPrintAnalysisDataSummary() { sb.replace(sb.length() - 2, sb.length(), ""); sb.append("\n"); sb.append(String.format("%30s", "Block count: ")) - .append(String.format("%-3s", massSpecExtractedData.getBlocksDataLite().size())) - .append(String.format("%-3s", "each with " + massSpecExtractedData.getBlocksDataLite().get(1).cycleData().length) + " cycles"); + .append(String.format("%-3s", massSpecExtractedData.getBlocksDataLite().size())); + if (massSpecExtractedData.getBlocksDataLite().size() > 0) { + sb.append(String.format("%-3s", "each with " + massSpecExtractedData.getBlocksDataLite().get(1).cycleData().length) + " cycles"); + } sb.append("\n"); } else { sb.append(String.format("%30s", "Column headers: ")); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataModels/dataLiteOne/initializers/AllBlockInitForDataLiteOne.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataModels/dataLiteOne/initializers/AllBlockInitForDataLiteOne.java index 43c280f6..199db182 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataModels/dataLiteOne/initializers/AllBlockInitForDataLiteOne.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataModels/dataLiteOne/initializers/AllBlockInitForDataLiteOne.java @@ -45,11 +45,11 @@ public static AllBlockInitForMCMC.PlottingData initBlockModels(AnalysisInterface } } - return new AllBlockInitForMCMC.PlottingData( + return (countOfBlocks > 0) ? new AllBlockInitForMCMC.PlottingData( null, null, singleBlockRawDataLiteSetRecords, - singleBlockRawDataLiteSetRecords[0].blockRawDataLiteArray().length, true, 1); + singleBlockRawDataLiteSetRecords[0].blockRawDataLiteArray().length, true, 1) : null; } private static SingleBlockRawDataLiteSetRecord prepareSingleBlockDataLiteCaseOne(int blockID, MassSpecExtractedData massSpecExtractedData) { diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/phoenix/PhoenixMassSpec.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/phoenix/PhoenixMassSpec.java index c2f36cfc..1831b7c7 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/phoenix/PhoenixMassSpec.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/phoenix/PhoenixMassSpec.java @@ -33,6 +33,8 @@ import java.util.*; import java.util.stream.Collectors; +import static java.lang.StrictMath.ceil; + /** * @author James F. Bowring */ @@ -73,11 +75,29 @@ public static MassSpecExtractedData extractMetaDataAndBlockDataFromIonvantageXLS } } + String localDateTimeZero = lines[startCtrlSheet + 21].split("\t")[2]; + // String sampleName = lines[startCtrlSheet + 7].split("\t")[3]; String methodName = lines[startCtrlSheet + 11].split("\t")[2]; int cyclesPerBlock = Integer.parseInt(lines[startCtrlSheet + 12].split("\t")[3]); - int blockCount = Integer.parseInt(lines[startCtrlSheet + 13].split("\t")[3]); - String localDateTimeZero = lines[startCtrlSheet + 21].split("\t")[2]; + + // April 2024 to handle aborted runs, find end of cycles and divide by cyclesperblock + int cyclesStart = startCycleSheet + 16; + int startBlockSheet = 0; + for (int i = startCycleSheet; i < lines.length; i++) { + if (lines[i].trim().compareTo("BLOCK") == 0) { + startBlockSheet = i; + break; + } + } + + int lastCycleNumber; + if (lines[startBlockSheet - 2].startsWith("0")) { + lastCycleNumber = 0; + } else { + lastCycleNumber = Integer.parseInt(lines[startBlockSheet - 2].split("\t")[0]); + } + int blockCount = (int) ceil(lastCycleNumber / cyclesPerBlock) + (int) Math.signum(lastCycleNumber % cyclesPerBlock); MassSpecExtractedData.MassSpecExtractedHeader header = new MassSpecExtractedData.MassSpecExtractedHeader( "IonVantage", @@ -90,12 +110,14 @@ public static MassSpecExtractedData extractMetaDataAndBlockDataFromIonvantageXLS ); massSpecExtractedData.setHeader(header); - int cyclesStart = startCycleSheet + 16; List> dataByBlocks = new ArrayList<>(); for (int blockID = 1; blockID <= blockCount; blockID++) { + List dataByBlock = new ArrayList<>(); for (int cycleNum = 1; cycleNum <= cyclesPerBlock; cycleNum++) { - dataByBlock.add(lines[cyclesStart + (blockID - 1) * cyclesPerBlock + cycleNum]); + if ((lastCycleNumber % cyclesPerBlock) == 0 || (lastCycleNumber % cyclesPerBlock) > cycleNum) { + dataByBlock.add(lines[cyclesStart + (blockID - 1) * cyclesPerBlock + cycleNum]); + } } dataByBlocks.add(dataByBlock); List cycleDataByLineSplit = new ArrayList<>(); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java index 2dc47d75..183ffa95 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java @@ -251,11 +251,14 @@ private String prettyPrintSequenceTable() { public String prettyPrintMethodSummary(boolean verbose) { StringBuilder retVal = new StringBuilder(); - retVal.append("Method: ").append(methodName).append(SPACES_100, 0, 55 - methodName.length()).append(verbose ? "\nSpecies: " : " Species: "); - List speciesAlphabetic = new ArrayList<>(speciesList); - Collections.sort(speciesAlphabetic, Comparator.comparing(s -> s.getAtomicMass())); - for (SpeciesRecordInterface species : speciesAlphabetic) { - retVal.append(species.prettyPrintShortForm() + " "); + retVal.append("Method: ").append(methodName).append(SPACES_100, 0, 55 - methodName.length()); + if (speciesList.size() > 0) { + retVal.append(verbose ? "\nSpecies: " : " Species: "); + List speciesAlphabetic = new ArrayList<>(speciesList); + Collections.sort(speciesAlphabetic, Comparator.comparing(s -> s.getAtomicMass())); + for (SpeciesRecordInterface species : speciesAlphabetic) { + retVal.append(species.prettyPrintShortForm() + " "); + } } if (verbose) { retVal.append("\nIsotopicRatios: "); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFraction.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFraction.java new file mode 100644 index 00000000..153b0f5f --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFraction.java @@ -0,0 +1,218 @@ +/* + * 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.sessions.analysis.outputs.etRedux; + +import com.thoughtworks.xstream.XStream; +import org.cirdles.tripoli.DataDictionary; +import org.cirdles.tripoli.utilities.xml.ETReduxFractionXMLConverter; +import org.cirdles.tripoli.utilities.xml.XMLSerializerInterface; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +/** + * Defines and produces fractions for use with www.earth-time.org ET_Redux program. + * Provides for recording the actual Tracer used to process the fraction, if any. + * ET_Redux previously known as UPb_Redux. This class ported from OG Tripoli. + */ + +public class ETReduxFraction implements Comparable, Serializable, XMLSerializerInterface { + private static String schemaURI = "https://raw.githubusercontent.com/EARTHTIME/Schema/UPbReduxInputXMLSchema.xsd"; + // Fields + private String sampleName; + private String fractionID; + private String ratioType; + private String pedigree; + private MeasuredRatioModel[] measuredRatios; + private double meanAlphaU; + private double meanAlphaPb; + private double r18O_16O; + private double labUBlankMass; + // april 2008 + private double r238_235b; + private double r238_235s; + private double tracerMass; + + public ETReduxFraction() { + this("", "", "", 0.0); + + this.measuredRatios = new MeasuredRatioModel[org.cirdles.tripoli.DataDictionary.UPbReduxMeasuredRatioNames.length]; + for (int i = 0; i < measuredRatios.length; i++) { + measuredRatios[i] = + new MeasuredRatioModel( + DataDictionary.UPbReduxMeasuredRatioNames[i], 0.0, 0.0, false, false); + } + } + + public ETReduxFraction(String sampleName, String fractionID, String ratioType, double r18O_16O) { + this.sampleName = sampleName; + this.fractionID = fractionID; + this.ratioType = ratioType; + this.pedigree = "None"; + this.meanAlphaU = 0.0; + this.meanAlphaPb = 0.0; + this.labUBlankMass = 0.0; + this.r18O_16O = r18O_16O; + this.r238_235b = 0.0; + this.r238_235s = 0.0; + this.tracerMass = 0.0; + } + + public static String getSchemaURI() { + return schemaURI; + } + + public String getSampleName() { + return sampleName; + } + + public void setSampleName(String sampleName) { + this.sampleName = sampleName; + } + + public String getFractionID() { + return fractionID; + } + + public void setFractionID(String fractionID) { + this.fractionID = fractionID; + } + + public String getRatioType() { + return ratioType; + } + + public void setRatioType(String ratioType) { + this.ratioType = ratioType; + } + + public String getPedigree() { + return pedigree; + } + + public void setPedigree(String pedigree) { + this.pedigree = pedigree; + } + + public MeasuredRatioModel[] getMeasuredRatios() { + return measuredRatios; + } + + public void setMeasuredRatios(MeasuredRatioModel[] measuredRatios) { + this.measuredRatios = measuredRatios; + } + + public double getMeanAlphaU() { + return meanAlphaU; + } + + public void setMeanAlphaU(double meanAlphaU) { + this.meanAlphaU = meanAlphaU; + } + + public double getMeanAlphaPb() { + return meanAlphaPb; + } + + public void setMeanAlphaPb(double meanAlphaPb) { + this.meanAlphaPb = meanAlphaPb; + } + + public double getR18O_16O() { + return r18O_16O; + } + + public void setR18O_16O(double r18O_16O) { + this.r18O_16O = r18O_16O; + } + + public double getLabUBlankMass() { + return labUBlankMass; + } + + public void setLabUBlankMass(double labUBlankMass) { + this.labUBlankMass = labUBlankMass; + } + + public double getR238_235b() { + return r238_235b; + } + + public void setR238_235b(double r238_235b) { + this.r238_235b = r238_235b; + } + + public double getR238_235s() { + return r238_235s; + } + + public void setR238_235s(double r238_235s) { + this.r238_235s = r238_235s; + } + + public double getTracerMass() { + return tracerMass; + } + + public void setTracerMass(double tracerMass) { + this.tracerMass = tracerMass; + } + + /** + * @param xstream + */ + @Override + public void customizeXstream(XStream xstream) { + xstream.registerConverter(new ETReduxFractionXMLConverter()); + xstream.alias("UPbReduxFraction", ETReduxFraction.class); + xstream.alias("MeasuredRatioModel", MeasuredRatioModel.class); + } + + /** + * @param o the object to be compared. + * @return + */ + @Override + public int compareTo(@NotNull Object o) { + if (o instanceof ETReduxFraction) { + return (sampleName + fractionID + ratioType) + .compareTo(((ETReduxFraction) o).sampleName + ((ETReduxFraction) o).fractionID + ((ETReduxFraction) o).ratioType); + } else return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (null == o || getClass() != o.getClass()) return false; + ETReduxFraction that = (ETReduxFraction) o; + return 0 == Double.compare(r18O_16O, that.r18O_16O) + && Objects.equals(sampleName, that.sampleName) + && Objects.equals(fractionID, that.fractionID) + && Objects.equals(ratioType, that.ratioType) + && Objects.equals(pedigree, that.pedigree) + && Arrays.equals(measuredRatios, that.measuredRatios); + } + + @Override + public int hashCode() { + int result = Objects.hash(sampleName, fractionID, ratioType, pedigree, r18O_16O); + result = 31 * result + Arrays.hashCode(measuredRatios); + return result; + } +} diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModel.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModel.java new file mode 100644 index 00000000..e7f03784 --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModel.java @@ -0,0 +1,136 @@ +/* + * 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.sessions.analysis.outputs.etRedux; + +import com.thoughtworks.xstream.XStream; +import org.cirdles.tripoli.utilities.xml.MeasuredRatioModelXMLConverter; +import org.cirdles.tripoli.utilities.xml.XMLSerializerInterface; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Ported from OG Tripoli; based on Bowring's ValueModel + */ +public class MeasuredRatioModel implements Comparable, Serializable, XMLSerializerInterface { + private String name; + private double value; + private String uncertaintyType; + private double oneSigma; + private boolean fracCorr; // fractionation corrected by Tripoli + private boolean oxideCorr; // oxide corrected by Tripoli + + public MeasuredRatioModel() { + } + + public MeasuredRatioModel( + String name, double value, double oneSigma, boolean fracCorr, boolean oxideCorr) { + this.name = name; + this.value = value; + this.uncertaintyType = "PCT"; + this.oneSigma = oneSigma; + this.fracCorr = fracCorr; + this.oxideCorr = oxideCorr; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getValue() { + return value; + } + + public void setValue(double value) { + this.value = value; + } + + public String getUncertaintyType() { + return uncertaintyType; + } + + public void setUncertaintyType(String uncertaintyType) { + this.uncertaintyType = uncertaintyType; + } + + public double getOneSigma() { + return oneSigma; + } + + public void setOneSigma(double oneSigma) { + this.oneSigma = oneSigma; + } + + public boolean isFracCorr() { + return fracCorr; + } + + public void setFracCorr(boolean fracCorr) { + this.fracCorr = fracCorr; + } + + public boolean isOxideCorr() { + return oxideCorr; + } + + public void setOxideCorr(boolean oxideCorr) { + this.oxideCorr = oxideCorr; + } + + /** + * @param xstream + */ + @Override + public void customizeXstream(XStream xstream) { + xstream.registerConverter(new MeasuredRatioModelXMLConverter()); + xstream.alias("MeasuredRatioModel", MeasuredRatioModel.class); + } + + /** + * @param o the object to be compared. + * @return + */ + @Override + public int compareTo(@NotNull Object o) { + if (o instanceof MeasuredRatioModel) { + return (name + value).compareTo(((MeasuredRatioModel) o).name + ((MeasuredRatioModel) o).value); + } else return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (null == o || getClass() != o.getClass()) return false; + MeasuredRatioModel that = (MeasuredRatioModel) o; + return 0 == Double.compare(value, that.value) + && 0 == Double.compare(oneSigma, that.oneSigma) + && fracCorr == that.fracCorr + && oxideCorr == that.oxideCorr + && Objects.equals(name, that.name) + && Objects.equals(uncertaintyType, that.uncertaintyType); + } + + @Override + public int hashCode() { + return Objects.hash(name, value, uncertaintyType, oneSigma, fracCorr, oxideCorr); + } +} diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/ETReduxFractionXMLConverter.java b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/ETReduxFractionXMLConverter.java new file mode 100644 index 00000000..c8c5865e --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/ETReduxFractionXMLConverter.java @@ -0,0 +1,200 @@ +/* + * 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.utilities.xml; + +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import org.cirdles.tripoli.sessions.analysis.outputs.etRedux.ETReduxFraction; +import org.cirdles.tripoli.sessions.analysis.outputs.etRedux.MeasuredRatioModel; + +import java.util.ArrayList; +import java.util.Arrays; + +public class ETReduxFractionXMLConverter implements Converter { + /** + * @param clazz + * @return + */ + @Override + public boolean canConvert(Class clazz) { + return clazz.equals(ETReduxFraction.class); + } + + /** + * @param value + * @param writer + * @param context + */ + @Override + public void marshal(Object value, HierarchicalStreamWriter writer, + MarshallingContext context) { + + ETReduxFraction etReduxFraction = (ETReduxFraction) value; + + writer.startNode("sampleName"); + writer.setValue(etReduxFraction.getSampleName()); + writer.endNode(); + + writer.startNode("fractionID"); + writer.setValue(etReduxFraction.getFractionID()); + writer.endNode(); + + writer.startNode("ratioType"); + writer.setValue(etReduxFraction.getRatioType()); + writer.endNode(); + + writer.startNode("pedigree"); + writer.setValue(etReduxFraction.getPedigree()); + writer.endNode(); + + writer.startNode("measuredRatios"); + // modified april 2010 to split "U" fractions from "Pb" fractions parts for LiveUpdate + String ratioType = etReduxFraction.getRatioType(); + ArrayList filteredMeasuredRatios = new ArrayList(); + if (ratioType.equalsIgnoreCase("U")) { + for (MeasuredRatioModel vm : etReduxFraction.getMeasuredRatios()) { + if (vm.getName().contains("3")) { + filteredMeasuredRatios.add(vm); + } + } + } else if (ratioType.equalsIgnoreCase("Pb")) { + for (MeasuredRatioModel vm : etReduxFraction.getMeasuredRatios()) { + if (vm.getName().contains("0")) { + filteredMeasuredRatios.add(vm); + } + } + } else { + filteredMeasuredRatios.addAll(Arrays.asList(etReduxFraction.getMeasuredRatios())); + } + // now convert arrayList to array + MeasuredRatioModel[] tempArray = new MeasuredRatioModel[filteredMeasuredRatios.size()]; + for (int i = 0; i < filteredMeasuredRatios.size(); i++) { + tempArray[i] = filteredMeasuredRatios.get(i); + } + context.convertAnother(tempArray); + writer.endNode(); + + writer.startNode("meanAlphaU"); + writer.setValue(String.valueOf(etReduxFraction.getMeanAlphaU())); + writer.endNode(); + + writer.startNode("meanAlphaPb"); + writer.setValue(String.valueOf(etReduxFraction.getMeanAlphaPb())); + writer.endNode(); + + writer.startNode("r18O16O"); + writer.setValue(String.valueOf(etReduxFraction.getR18O_16O())); + writer.endNode(); + + writer.startNode("labUBlankMass"); + writer.setValue(String.valueOf(etReduxFraction.getLabUBlankMass())); + writer.endNode(); + + writer.startNode("r238235b"); + writer.setValue(String.valueOf(etReduxFraction.getR238_235b())); + writer.endNode(); + + writer.startNode("r238235s"); + writer.setValue(String.valueOf(etReduxFraction.getR238_235s())); + writer.endNode(); + + writer.startNode("tracerMass"); + writer.setValue(String.valueOf(etReduxFraction.getTracerMass())); + writer.endNode(); + + } + + /** + * @param reader + * @param context + * @return + */ + @Override + public Object unmarshal(HierarchicalStreamReader reader, + UnmarshallingContext context) { + + ETReduxFraction etReduxFraction = new ETReduxFraction(); + + reader.moveDown(); + etReduxFraction.setSampleName(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setFractionID(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setRatioType(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setPedigree(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + if ("measuredRatios".equals(reader.getNodeName())) { + ArrayList ratios = new ArrayList<>(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + MeasuredRatioModel item = new MeasuredRatioModel(); + item = (MeasuredRatioModel) context.convertAnother(item, MeasuredRatioModel.class); + ratios.add(item); + reader.moveUp(); + } + // Convert to array + MeasuredRatioModel[] measuredRatios = new MeasuredRatioModel[ratios.size()]; + for (int i = 0; i < ratios.size(); i++) { + measuredRatios[i] = ratios.get(i); + } + etReduxFraction.setMeasuredRatios(measuredRatios); + } + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setMeanAlphaU(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setMeanAlphaPb(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setR18O_16O(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setLabUBlankMass(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setR238_235b(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setR238_235s(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + etReduxFraction.setTracerMass(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + return etReduxFraction; + } +} diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/MeasuredRatioModelXMLConverter.java b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/MeasuredRatioModelXMLConverter.java new file mode 100644 index 00000000..c943e4f1 --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/MeasuredRatioModelXMLConverter.java @@ -0,0 +1,131 @@ +/* + * 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.utilities.xml; + +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import org.cirdles.tripoli.sessions.analysis.outputs.etRedux.MeasuredRatioModel; + +public class MeasuredRatioModelXMLConverter implements Converter { + /** + * checks the argument clazz against this MeasuredRatioModel's + * Class. Used to ensure that the object about to be + * marshalled/unmarshalled is of the correct type. + * + * @param clazz Class of the Object you wish + * to convert to/from XML + * @return boolean - true if clazz matches + * MeasuredRatioModel's Class; else false. + * @pre argument clazz is a valid Class + * @post boolean is returned comparing clazz + * against MeasuredRatioModel.class + */ + public boolean canConvert(Class clazz) { + return clazz.equals(MeasuredRatioModel.class); + } + + /** + * writes the argument value to the XML file specified through writer + * + * @param value MeasuredRatioModel that you wish to write to a file + * @param writer stream to write through + * @param context MarshallingContext used to store generic data + * @pre value is a valid MeasuredRatioModel, + * writer is a valid HierarchicalStreamWriter, + * and context is a valid MarshallingContext + * @post value is written to the XML file specified via writer + */ + public void marshal(Object value, HierarchicalStreamWriter writer, + MarshallingContext context) { + + MeasuredRatioModel measuredRatio = (MeasuredRatioModel) value; + + writer.startNode("name"); + writer.setValue(measuredRatio.getName()); + writer.endNode(); + + writer.startNode("value"); + writer.setValue(String.valueOf(measuredRatio.getValue())); + writer.endNode(); + + writer.startNode("uncertaintyType"); + writer.setValue(measuredRatio.getUncertaintyType()); + writer.endNode(); + + writer.startNode("oneSigma"); + writer.setValue(String.valueOf(measuredRatio.getOneSigma())); + writer.endNode(); + + writer.startNode("fracCorr"); + writer.setValue(Boolean.toString(measuredRatio.isFracCorr())); + writer.endNode(); + + writer.startNode("oxideCorr"); + writer.setValue(Boolean.toString(measuredRatio.isOxideCorr())); + writer.endNode(); + + } + + /** + * reads a MeasuredRatioModel from the XML file specified + * through reader + * + * @param reader stream to read through + * @param context UnmarshallingContext used to store generic data + * @return MeasuredRatioModel - MeasuredRatioModel + * read from file specified by reader + * @pre reader leads to a valid MeasuredRatioModel + * @post returns the MeasuredRatioModel read from the XML file + */ + public Object unmarshal(HierarchicalStreamReader reader, + UnmarshallingContext context) { + + MeasuredRatioModel measuredRatio = new MeasuredRatioModel(); + + reader.moveDown(); + measuredRatio.setName(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + measuredRatio.setValue(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + // temp hack dec 2007 during transition to new data format + reader.moveDown(); + if ("uncertaintyType".equals(reader.getNodeName())) { + measuredRatio.setUncertaintyType(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + } + measuredRatio.setOneSigma(Double.parseDouble(reader.getValue())); + reader.moveUp(); + + reader.moveDown(); + measuredRatio.setFracCorr((reader.getValue().equalsIgnoreCase("true")) ? true : false); + reader.moveUp(); + + reader.moveDown(); + measuredRatio.setOxideCorr((reader.getValue().equalsIgnoreCase("true")) ? true : false); + reader.moveUp(); + + return measuredRatio; + } +} diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/XMLSerializerInterface.java b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/XMLSerializerInterface.java new file mode 100644 index 00000000..54f64fd9 --- /dev/null +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/utilities/xml/XMLSerializerInterface.java @@ -0,0 +1,104 @@ +/* + * Copyright 2016 James F. Bowring 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.utilities.xml; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; +import com.thoughtworks.xstream.security.AnyTypePermission; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author James F. Bowring + */ +public interface XMLSerializerInterface { + + /** + * Use XStream to serialize object to XML + * + * @param filename + */ + default void serializeXMLObject(String filename) { + OutputStreamWriter outFile = null; + try { + XStream xstream = new XStream(new DomDriver()); + xstream.addPermission(AnyTypePermission.ANY); + customizeXstream(xstream); + String xml = xstream.toXML(this).trim(); + xml = customizeXML(xml).trim(); + + outFile = new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8); + try (PrintWriter out = new PrintWriter(outFile)) { + // Write xml to file + out.println(xml); + out.flush(); + } + } catch (IOException ex) { + Logger.getLogger(XMLSerializerInterface.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + if (outFile != null) { + outFile.close(); + } + } catch (IOException ex) { + Logger.getLogger(XMLSerializerInterface.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + /** + * @param filename + * @param doValidate + * @return + */ + default Object readXMLObject(String filename, boolean doValidate) { + + Object myModelClassInstance = null; + + try { + InputStream bis = new ByteArrayInputStream(Files.readAllBytes(Paths.get(filename))); + Reader reader = new InputStreamReader(bis, StandardCharsets.UTF_8); + + XStream xstream = new XStream(new DomDriver()); + xstream.addPermission(AnyTypePermission.ANY); + customizeXstream(xstream); + + myModelClassInstance = xstream.fromXML(reader); + } catch (Exception iOException) { + // do nothing for now + } + + return myModelClassInstance; + } + + /** + * @param xstream + */ + void customizeXstream(XStream xstream); + + /** + * @param xml + * @return + */ + default String customizeXML(String xml) { + return xml; + } +} \ No newline at end of file diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/valueModels/ValueModel.java b/TripoliCore/src/main/java/org/cirdles/tripoli/valueModels/ValueModel.java index e6558171..34756cd0 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/valueModels/ValueModel.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/valueModels/ValueModel.java @@ -31,28 +31,28 @@ public class ValueModel implements Serializable, Comparable, ValueMo private static final long serialVersionUID = -2165611302657545964L; - private String name; - private BigDecimal value; - private BigDecimal analyticalOneSigmaAbs; - private BigDecimal systematicOneSigmaAbs; + protected String name; + protected BigDecimal value; + protected BigDecimal analyticalOneSigmaAbs; + protected BigDecimal systematicOneSigmaAbs; - private ValueModel() { + protected ValueModel() { this(DEFAULT_OBJECT_NAME, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); } - private ValueModel(String name) { + protected ValueModel(String name) { this(name, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); } - private ValueModel(String name, BigDecimal value) { + protected ValueModel(String name, BigDecimal value) { this(name, value, BigDecimal.ZERO, BigDecimal.ZERO); } - private ValueModel(String name, BigDecimal value, BigDecimal analyticalOneSigmaAbs) { + protected ValueModel(String name, BigDecimal value, BigDecimal analyticalOneSigmaAbs) { this(name, value, analyticalOneSigmaAbs, BigDecimal.ZERO); } - private ValueModel(String name, BigDecimal value, BigDecimal analyticalOneSigmaAbs, BigDecimal systematicOneSigmaAbs) { + protected ValueModel(String name, BigDecimal value, BigDecimal analyticalOneSigmaAbs, BigDecimal systematicOneSigmaAbs) { this.name = Objects.requireNonNull(name); this.value = value; this.analyticalOneSigmaAbs = analyticalOneSigmaAbs; diff --git a/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/UPbReduxInputXMLSchema.xsd b/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/UPbReduxInputXMLSchema.xsd new file mode 100644 index 00000000..035a76e8 --- /dev/null +++ b/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/UPbReduxInputXMLSchema.xsd @@ -0,0 +1,69 @@ + + + + + This schema defines the contents of the U-Pb fraction input to + EARTHTIME U-Pb_Redux software. + + Copyright 2006-2016 James F. Bowring and EARTHTIME + + 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. + + Author: James F. Bowring[smtp:bowring@gmail.com] + + Created: 1.January.2007 + Revised: 1.January.2008 + Revised: 8.April.2008 + Revised: 5.April.2009 + Revised: 27.June.2012 + Revised: 23.December.2015 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/listOfResourceFiles.txt b/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/listOfResourceFiles.txt index ea579e60..2a6fd6a8 100644 --- a/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/listOfResourceFiles.txt +++ b/TripoliCore/src/main/resources/org/cirdles/tripoli/schema/listOfResourceFiles.txt @@ -1,3 +1,4 @@ README.txt https://raw.githubusercontent.com/EARTHTIME/Schema/master/TracerUPbModelXMLSchema.xsd -https://raw.githubusercontent.com/EARTHTIME/Schema/master/ValueModelXMLSchema.xsd \ No newline at end of file +https://raw.githubusercontent.com/EARTHTIME/Schema/master/ValueModelXMLSchema.xsd +https://raw.githubusercontent.com/EARTHTIME/Schema/master/UPbReduxInputXMLSchema.xsd diff --git a/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFractionTest.java b/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFractionTest.java new file mode 100644 index 00000000..ef759bde --- /dev/null +++ b/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/ETReduxFractionTest.java @@ -0,0 +1,34 @@ +package org.cirdles.tripoli.sessions.analysis.outputs.etRedux; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ETReduxFractionTest { + + String fileNameForXML = "testETReduxFraction.xml"; + MeasuredRatioModel[] measuredRatioModels = new MeasuredRatioModel[3]; + + @BeforeEach + void setUp() { + measuredRatioModels[0] = new MeasuredRatioModel("TestRatioModelA3", 12345.6789, 98765.4321, true, false); + measuredRatioModels[1] = new MeasuredRatioModel("TestRatioModelB3", -12345.6789, 98765.4321, false, true); + measuredRatioModels[2] = new MeasuredRatioModel("TestRatioModelC3", 12345.6789, -98765.4321, false, false); + + } + + @AfterEach + void tearDown() { + } + + @Test + void validateSerializationXML() { + ETReduxFraction etReduxFraction = new ETReduxFraction();//"Sample1", "Fraction1", "U", 1.025); +// etReduxFraction.setMeasuredRatios(measuredRatioModels); + etReduxFraction.serializeXMLObject(fileNameForXML); + ETReduxFraction etReduxFraction2 = (ETReduxFraction) etReduxFraction.readXMLObject(fileNameForXML, false); + assertEquals(etReduxFraction, etReduxFraction2); + } +} \ No newline at end of file diff --git a/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModelTest.java b/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModelTest.java new file mode 100644 index 00000000..28441317 --- /dev/null +++ b/TripoliCore/src/test/java/org/cirdles/tripoli/sessions/analysis/outputs/etRedux/MeasuredRatioModelTest.java @@ -0,0 +1,33 @@ +package org.cirdles.tripoli.sessions.analysis.outputs.etRedux; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MeasuredRatioModelTest { + + MeasuredRatioModel measuredRatioModel = new MeasuredRatioModel("TestRatioModel", 12345.6789, 98765.4321, true, false); + String fileNameForXML = "testMeasuredRatioModel.xml"; + + @BeforeEach + void setUp() { + } + + @AfterEach + void tearDown() throws IOException { + Files.delete(new File(fileNameForXML).toPath()); + } + + @Test + void validateSerializationXML() { + measuredRatioModel.serializeXMLObject(fileNameForXML); + MeasuredRatioModel measuredRatioModel2 = (MeasuredRatioModel) measuredRatioModel.readXMLObject(fileNameForXML, false); + assertEquals(measuredRatioModel, measuredRatioModel2); + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/common-build.gradle.kts b/buildSrc/src/main/kotlin/common-build.gradle.kts index 8099e849..83a86e24 100644 --- a/buildSrc/src/main/kotlin/common-build.gradle.kts +++ b/buildSrc/src/main/kotlin/common-build.gradle.kts @@ -50,7 +50,7 @@ dependencies { val mavenArtifactId = name val mavenGroupId = "org.cirdles" // preserve double quotes in mavenVersion as Tripoli uses regex based on them to check on latest version -val mavenVersion = "0.4.9"//3 APR 2024 +val mavenVersion = "0.5.0"//18 APR 2024 object Versions { const val junitVersion = "5.8.2" From e92e34a0546acfd3901780847422be6c8f1ddd71 Mon Sep 17 00:00:00 2001 From: Jim Bowring Date: Thu, 25 Apr 2024 09:25:34 -0400 Subject: [PATCH 4/4] progress release --- .../userFunctions/UserFunction.java | 18 +++++++ .../tripoli/sessions/analysis/Analysis.java | 6 +-- .../MassSpecExtractedData.java | 16 ++++++ .../MassSpecOutputBlockRecordLite.java | 14 ++++++ .../analysis/methods/AnalysisMethod.java | 50 ++++++++++++++++++- .../src/main/kotlin/common-build.gradle.kts | 2 +- 6 files changed, 100 insertions(+), 6 deletions(-) diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/expressions/userFunctions/UserFunction.java b/TripoliCore/src/main/java/org/cirdles/tripoli/expressions/userFunctions/UserFunction.java index 08d177d8..211b0d7d 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/expressions/userFunctions/UserFunction.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/expressions/userFunctions/UserFunction.java @@ -26,13 +26,19 @@ public class UserFunction implements Serializable { @Serial private static final long serialVersionUID = -5408855769497340457L; private String name; + private String etReduxName; private int columnIndex; private boolean treatAsIsotopicRatio; private boolean displayed; private boolean inverted; + public UserFunction(String name, int columnIndex) { + this(name, columnIndex, false, true); + } + public UserFunction(String name, int columnIndex, boolean treatAsIsotopicRatio, boolean displayed) { this.name = name; + this.etReduxName = ""; this.columnIndex = columnIndex; this.treatAsIsotopicRatio = treatAsIsotopicRatio; this.displayed = displayed; @@ -43,6 +49,14 @@ public String getName() { return name; } + public String getEtReduxName() { + return etReduxName; + } + + public void setEtReduxName(String etReduxName) { + this.etReduxName = etReduxName; + } + public String showInvertedRatioName() { String retVal = name; if (treatAsIsotopicRatio) { @@ -60,6 +74,10 @@ public boolean isTreatAsIsotopicRatio() { return treatAsIsotopicRatio; } + public void setTreatAsIsotopicRatio(boolean treatAsIsotopicRatio) { + this.treatAsIsotopicRatio = treatAsIsotopicRatio; + } + public boolean isDisplayed() { return displayed; } diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java index 367ca844..ce0ecd7f 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/Analysis.java @@ -249,11 +249,11 @@ public void extractMassSpecDataFromPath(Path dataFilePath) } } else { // case1 + analysisName = dataFilePath.toFile().getName().substring(0, dataFilePath.toFile().getName().length() - 4); analysisMethod = AnalysisMethod.createAnalysisMethodFromCase1(massSpecExtractedData); initializeBlockProcessing(); } - analysisName = dataFilePath.toFile().getName(); } public void initializeBlockProcessing() { @@ -423,7 +423,7 @@ public final String prettyPrintAnalysisDataSummary() { StringBuilder sb = new StringBuilder(); if (getAnalysisCaseNumber() == 1) { sb.append(String.format("%30s", "Column headers: ")); - for (String header : massSpecExtractedData.getColumnHeaders()) { + for (String header : massSpecExtractedData.getUsedColumnHeaders()) { sb.append(header + ", "); } sb.replace(sb.length() - 2, sb.length(), ""); @@ -436,7 +436,7 @@ public final String prettyPrintAnalysisDataSummary() { sb.append("\n"); } else { sb.append(String.format("%30s", "Column headers: ")); - for (String header : massSpecExtractedData.getColumnHeaders()) { + for (String header : massSpecExtractedData.getUsedColumnHeaders()) { sb.append(header + ", "); } sb.replace(sb.length() - 2, sb.length(), ""); diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecExtractedData.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecExtractedData.java index 58dbf212..1b05042b 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecExtractedData.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecExtractedData.java @@ -190,6 +190,12 @@ public int[] assignBlockIdToSessionTimeLite() { return blockIDs; } + public void expandCycleDataForUraniumOxideCorrection(int r270_267ColumnIndex, int r265_267ColumnIndex, double r18O_16O) { + for (Integer blockID : blocksDataLite.keySet()) { + blocksDataLite.put(blockID, blocksDataLite.get(blockID).expandForUraniumOxideCorrection(r270_267ColumnIndex, r265_267ColumnIndex, r18O_16O)); + } + } + public MassSpectrometerContextEnum getMassSpectrometerContext() { return massSpectrometerContext; } @@ -214,6 +220,16 @@ public void setColumnHeaders(String[] columnHeaders) { this.columnHeaders = columnHeaders; } + public String[] getUsedColumnHeaders() { + List usedColumnHeadersList = new ArrayList<>(); + for (String ch : columnHeaders) { + if (ch != null) { + usedColumnHeadersList.add(ch); + } + } + return usedColumnHeadersList.toArray(new String[0]); + } + public DetectorSetup getDetectorSetup() { return detectorSetup; } diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecOutputBlockRecordLite.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecOutputBlockRecordLite.java index da3ddb0b..6e03cdb1 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecOutputBlockRecordLite.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/massSpectrometerModels/dataSourceProcessors/MassSpecOutputBlockRecordLite.java @@ -26,5 +26,19 @@ public record MassSpecOutputBlockRecordLite( int blockID, double[][] cycleData ) implements Serializable { + public MassSpecOutputBlockRecordLite expandForUraniumOxideCorrection(int r270_267ColumnIndex, int r265_267ColumnIndex, double r18O_16O) { + double[][] cycleDataExpand = new double[cycleData.length][]; + for (int row = 0; row < cycleData.length; row++) { + cycleDataExpand[row] = new double[cycleData[row].length + 3]; + System.arraycopy(cycleData[row], 0, cycleDataExpand[row], 0, cycleData[row].length); + cycleDataExpand[row][cycleData[row].length + 0] + = cycleData[row][r265_267ColumnIndex] / (1.0 - 2.0 * r18O_16O * cycleData[row][r265_267ColumnIndex]); + cycleDataExpand[row][cycleData[row].length + 1] + = cycleData[row][r270_267ColumnIndex] / (1.0 - 2.0 * r18O_16O * cycleData[row][r270_267ColumnIndex]); + cycleDataExpand[row][cycleData[row].length + 2] + = cycleDataExpand[row][cycleData[row].length + 1] / cycleDataExpand[row][cycleData[row].length + 0]; + } + return new MassSpecOutputBlockRecordLite(blockID, cycleDataExpand); + } } \ No newline at end of file diff --git a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java index 183ffa95..ccf84130 100644 --- a/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java +++ b/TripoliCore/src/main/java/org/cirdles/tripoli/sessions/analysis/methods/AnalysisMethod.java @@ -81,14 +81,60 @@ public static AnalysisMethod initializeAnalysisMethod(String methodName, MassSpe public static AnalysisMethod createAnalysisMethodFromCase1( MassSpecExtractedData massSpecExtractedData) { + int r270_267ColumnIndex = -1; + int r265_267ColumnIndex = -1; AnalysisMethod analysisMethod = new AnalysisMethod("Derived for Case1", massSpecExtractedData.getMassSpectrometerContext()); String[] columnHeaders = massSpecExtractedData.getColumnHeaders(); // ignore first two columns: Cycle, Time String regex = "[^alpha].*\\d?:?\\(?\\d{2,3}.{0,2}\\/\\d?:?\\d{2,3}.{0,2}.*"; + for (int i = 2; i < columnHeaders.length; i++) { -// System.out.println(columnHeaders[i] + " " + columnHeaders[i].matches(regex)); - UserFunction userFunction = new UserFunction(columnHeaders[i].trim(), i - 2, columnHeaders[i].matches(regex), true);//columnHeaders[i].matches(regex)); + UserFunction userFunction = new UserFunction(columnHeaders[i].trim(), i - 2); + if (columnHeaders[i].matches(regex)) { + userFunction.setTreatAsIsotopicRatio(true); + int indexOfDivide = columnHeaders[i].indexOf("/"); + // assume three digits / three digits + String numerator = columnHeaders[i].substring(indexOfDivide - 3, 3); + String denominator = columnHeaders[i].substring(indexOfDivide + 1, indexOfDivide + 4); + String etReduxRatioName = numerator + "_" + denominator; + userFunction.setEtReduxName(etReduxRatioName); + + if (etReduxRatioName.compareTo("270_267") == 0) { + r270_267ColumnIndex = i - 2; + } + if (etReduxRatioName.compareTo("265_267") == 0) { + r265_267ColumnIndex = i - 2; + } + } + analysisMethod.getUserFunctions().add(userFunction); + } + + // Uranium Oxide Correction : https://docs.google.com/document/d/14PPEDEJPylNMavpJDpYSuemNb0gF5dz_To3Ek1Y_Agw/edit#bookmark=id.xvyds659gu4x + if ((r270_267ColumnIndex > -1) && (r265_267ColumnIndex > -1)) { + massSpecExtractedData.expandCycleDataForUraniumOxideCorrection(r270_267ColumnIndex, r265_267ColumnIndex, 0.00205); + String[] columnHeadersExpanded = new String[columnHeaders.length + 3]; + + System.arraycopy(columnHeaders, 0, columnHeadersExpanded, 0, columnHeaders.length); + + columnHeadersExpanded[columnHeaders.length + 0] = "233/235oc"; + UserFunction userFunction = new UserFunction(columnHeadersExpanded[columnHeaders.length], columnHeaders.length - 2, true, true); + userFunction.setEtReduxName("r233_235oc"); + analysisMethod.getUserFunctions().add(userFunction); + + columnHeadersExpanded[columnHeaders.length + 1] = "238/235oc"; + userFunction = new UserFunction(columnHeadersExpanded[columnHeaders.length + 1], columnHeaders.length - 1, true, true); + userFunction.setEtReduxName("r238_235oc"); + analysisMethod.getUserFunctions().add(userFunction); + + columnHeadersExpanded[columnHeaders.length + 2] = "238/233oc"; + userFunction = new UserFunction(columnHeadersExpanded[columnHeaders.length + 2], columnHeaders.length, true, true); + userFunction.setEtReduxName("r238_233oc"); analysisMethod.getUserFunctions().add(userFunction); + + massSpecExtractedData.setColumnHeaders(columnHeadersExpanded); + + System.out.println(columnHeaders[r270_267ColumnIndex + 2]); + } return analysisMethod; diff --git a/buildSrc/src/main/kotlin/common-build.gradle.kts b/buildSrc/src/main/kotlin/common-build.gradle.kts index 83a86e24..2edd2436 100644 --- a/buildSrc/src/main/kotlin/common-build.gradle.kts +++ b/buildSrc/src/main/kotlin/common-build.gradle.kts @@ -50,7 +50,7 @@ dependencies { val mavenArtifactId = name val mavenGroupId = "org.cirdles" // preserve double quotes in mavenVersion as Tripoli uses regex based on them to check on latest version -val mavenVersion = "0.5.0"//18 APR 2024 +val mavenVersion = "0.5.0"//25 APR 2024 object Versions { const val junitVersion = "5.8.2"