org.cirdles.squid.tasks.squidTask25.TaskSquid25.java Source code

Java tutorial

Introduction

Here is the source code for org.cirdles.squid.tasks.squidTask25.TaskSquid25.java

Source

/*
 * Copyright 2017 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.squid.tasks.squidTask25;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.extractor.ExcelExtractor;
import org.cirdles.squid.constants.Squid3Constants.TaskTypeEnum;
import org.cirdles.squid.tasks.expressions.parsing.ShuntingYard;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.COM206PB_PCT;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.COM208PB_PCT;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.DEFAULT_BACKGROUND_MASS_LABEL;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.PARENT_ELEMENT_CONC_CONST;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.R206PB_238U;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.R207PB_206PB;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.R207PB_235U;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.UNCOR206PB238U_CALIB_CONST;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.UNCOR208PB232TH_CALIB_CONST;
import static org.cirdles.squid.tasks.expressions.builtinExpressions.BuiltInExpressionsDataDictionary.TH_U_EXP_DEFAULT;

/**
 *
 * @author James F. Bowring
 */
public class TaskSquid25 implements Serializable {

    private static final long serialVersionUID = -2805382700088270719L;

    private String squidVersion;
    private String squidTaskFileName;
    private TaskTypeEnum taskType;
    private String taskName;
    private String taskDescription;
    private String labName;
    private String authorName;
    private List<String> nominalMasses;
    private List<String> ratioNames;
    private String backgroundMass;
    private String parentNuclide;
    private boolean directAltPD;
    private String primaryParentElement;
    private List<TaskSquid25Equation> task25Equations;
    private List<String> constantNames;
    private List<String> constantValues;

    private Map<String, String> specialSquidFourExpressionsMap;

    private static TaskSquid25 taskSquid25;

    public static TaskSquid25 importSquidTaskFile(File squidTaskFile) {

        taskSquid25 = null;

        try {
            InputStream inp = new FileInputStream(squidTaskFile);
            HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(inp));
            ExcelExtractor extractor = new org.apache.poi.hssf.extractor.ExcelExtractor(wb);

            extractor.setFormulasNotResults(true);
            extractor.setIncludeSheetNames(false);
            String text = extractor.getText();

            String[] lines = text.split("\n");
            boolean isSquid2_20 = false;
            if (lines[0].startsWith("Created by SQUID")) {
                taskSquid25 = new TaskSquid25();
                taskSquid25.constantNames = new ArrayList<>();
                taskSquid25.constantValues = new ArrayList<>();

                taskSquid25.squidVersion = lines[0].split("\t")[1];
                // July 2018 detect if version 2.20
                isSquid2_20 = (taskSquid25.squidVersion.startsWith("2.20"));

                int firstRow = Integer.parseInt(lines[1].split("\t")[1]) - 1;

                taskSquid25.squidTaskFileName = lines[firstRow].split("\t")[1];
                taskSquid25.taskType = TaskTypeEnum
                        .valueOf(lines[firstRow + 1].split("\t")[1].toUpperCase(Locale.ENGLISH));
                taskSquid25.taskName = lines[firstRow + 2].split("\t")[1];
                taskSquid25.taskDescription = lines[firstRow + 3].split("\t")[1];

                taskSquid25.authorName = "";
                taskSquid25.labName = lines[firstRow + 7].split("\t")[1];

                String[] nominalMasses = lines[firstRow + 13].split("\t");
                int countOfMasses = Integer.valueOf(nominalMasses[1]);
                taskSquid25.nominalMasses = new ArrayList<>();
                for (int i = 0; i < countOfMasses; i++) {
                    taskSquid25.nominalMasses.add(nominalMasses[i + 2]);
                }

                // July 2018
                // decrement first row to handle missing line for Hidden Masses in Squid 2.20
                if (isSquid2_20) {
                    firstRow--;
                }

                String[] ratioStrings = lines[firstRow + 15].split("\t");
                if (isSquid2_20 && ratioStrings[0].toUpperCase(Locale.ENGLISH).startsWith("HIDDEN")) {
                    // special case of 2.2 where this row exists
                    firstRow++;
                    ratioStrings = lines[firstRow + 15].split("\t");
                }
                int countOfRatios = Integer.valueOf(ratioStrings[1]);
                taskSquid25.ratioNames = new ArrayList<>();
                for (int i = 0; i < countOfRatios; i++) {
                    taskSquid25.ratioNames.add(ratioStrings[i + 2]);
                }

                String[] backgroundStrings = lines[firstRow + 19].split("\t");
                taskSquid25.backgroundMass = backgroundStrings[1];

                String[] parentNuclideStrings = lines[firstRow + 20].split("\t");
                taskSquid25.parentNuclide = parentNuclideStrings[1];

                String[] directAltPDStrings = lines[firstRow + 21].split("\t");
                taskSquid25.directAltPD = Boolean.valueOf(directAltPDStrings[1]);

                taskSquid25.task25Equations = new ArrayList<>();

                // determine where uranium or thorium is primary or secondary
                String primaryUThEqnName = UNCOR206PB238U_CALIB_CONST;
                String primaryUThEqnOtherName = UNCOR208PB232TH_CALIB_CONST;

                taskSquid25.specialSquidFourExpressionsMap = new TreeMap<>();

                String[] primaryUThPbEqn = lines[firstRow + 22].split("\t");
                if (primaryUThPbEqn.length > 1) {
                    if (taskSquid25.parentNuclide.contains("232")) {
                        primaryUThEqnName = UNCOR208PB232TH_CALIB_CONST;
                        primaryUThEqnOtherName = UNCOR206PB238U_CALIB_CONST;
                    }
                    taskSquid25.specialSquidFourExpressionsMap.put(primaryUThEqnName,
                            prepareSquid25ExcelEquationStringForSquid3(primaryUThPbEqn[1]));
                }

                String[] secondaryUThPbEqn = lines[firstRow + 23].split("\t");
                if (secondaryUThPbEqn.length > 1) {
                    taskSquid25.specialSquidFourExpressionsMap.put(primaryUThEqnOtherName,
                            prepareSquid25ExcelEquationStringForSquid3(secondaryUThPbEqn[1]));
                }

                String[] ThUEqn = lines[firstRow + 24].split("\t");
                if (ThUEqn.length > 1) {
                    taskSquid25.specialSquidFourExpressionsMap.put(TH_U_EXP_DEFAULT,
                            prepareSquid25ExcelEquationStringForSquid3(ThUEqn[1]));
                }

                String[] ppmParentEqn = lines[firstRow + 25].split("\t");
                if (ppmParentEqn.length > 1) {
                    taskSquid25.specialSquidFourExpressionsMap.put(PARENT_ELEMENT_CONC_CONST,
                            prepareSquid25ExcelEquationStringForSquid3(ppmParentEqn[1]));
                }

                String[] equations = lines[firstRow + 26].split("\t");
                int countOfEquations = Integer.valueOf(equations[1]);

                String[] equationNames = lines[firstRow + 27].split("\t");

                // June 2019 skip Hidden row 34
                String[] switchST = lines[firstRow + 28].split("\t");
                if (switchST[0].toUpperCase(Locale.ENGLISH).startsWith("HIDDEN")) {
                    firstRow++;
                }

                // these switches split into a//n array of length equations mius 1 in Squid2.20 due to missing count entry
                switchST = lines[firstRow + 28].split("\t");

                String[] switchSA = lines[firstRow + 29].split("\t");

                String[] switchSC = lines[firstRow + 30].split("\t");

                String[] switchNU = lines[firstRow + 32].split("\t");

                // run constants first so can detect in equations
                String[] constantNamesSource = lines[firstRow + 40].split("\t");
                String[] constantValuesSource = lines[firstRow + 41].split("\t");

                int countOfConstants = 0;
                if (constantNamesSource.length > 1) {
                    countOfConstants = Integer.valueOf(constantNamesSource[1]);
                }

                for (int i = 0; i < countOfConstants; i++) {
                    taskSquid25.constantNames.add(constantNamesSource[i + 2].replaceFirst("_", ""));
                    taskSquid25.constantValues.add(constantValuesSource[i + 2]);
                }

                for (int i = 0; i < countOfEquations; i++) {
                    // handle backwards logic of Squid25 where both ST, SA false, means both True
                    boolean switchRM = Boolean.parseBoolean(switchST[i + (isSquid2_20 ? 1 : 2)]);
                    boolean switchUN = Boolean.parseBoolean(switchSA[i + (isSquid2_20 ? 1 : 2)]);
                    if (!switchRM && !switchUN) {
                        switchRM = true;
                        switchUN = true;
                    }

                    String excelExpression = prepareSquid25ExcelEquationStringForSquid3(equations[i + 2]);
                    if (excelExpression.length() > 0) {
                        //detect if name contains "Age" or "abs" - undo change to % for errors
                        if ((equationNames[i + 2].toUpperCase(Locale.ENGLISH).contains("ABS"))
                                || (equationNames[i + 2].toUpperCase(Locale.ENGLISH).contains("AGE"))) {
                            if (excelExpression.startsWith("[%\"")) {
                                excelExpression = excelExpression.replaceFirst("\\[%\"", "\\[\"");
                            }
                        }
                        taskSquid25.task25Equations.add(new TaskSquid25Equation(excelExpression,
                                prepareSquid25ExcelEquationNameForSquid3(equationNames[i + 2]), switchRM, switchUN,
                                Boolean.parseBoolean(switchSC[i + (isSquid2_20 ? 1 : 2)]),
                                Boolean.parseBoolean(switchNU[i + (isSquid2_20 ? 1 : 2)]), false, false));
                    }
                }
            }
        } catch (IOException iOException) {
        }

        return taskSquid25;
    }

    private static String prepareSquid25ExcelEquationStringForSquid3(String excelString) {
        String retVal = "";

        retVal = excelString.replace("|", "");
        retVal = retVal.replace("[\"Total 204 cts/sec\"]", "totalCps([\"204\"])");
        retVal = retVal.replace("[\"Total 206cts/sec\"]", "totalCps([\"206\"])");
        retVal = retVal.replace("[\"Bkrd cts/sec\"]", "totalCps([\"" + DEFAULT_BACKGROUND_MASS_LABEL + "\"])");
        retVal = retVal.replace("[\"Bkrdcts/sec\"]", "totalCps([\"" + DEFAULT_BACKGROUND_MASS_LABEL + "\"])");
        retVal = retVal.replace("9511", "95");
        retVal = retVal.replace("(Ma)", "");
        // assume most calls to uncertainty are for percent
        retVal = retVal.replace("[\"", "[%\"");

        // June 2019 fix Allen Kennedy's use of bad quotes
        retVal = retVal.replace("", "\"");
        retVal = retVal.replace("?", "\"");

        // regex for robreg with four arguments = robreg.*\)
        Pattern squid25FunctionPattern = Pattern.compile("^(.*)[r,R]obreg.*\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.matches()) {
            String[] robregParts = matcher.group().split(",");
            if (robregParts.length > 1) {
                retVal = retVal.replace(matcher.group(),
                        robregParts[0] + "," + robregParts[1] + (robregParts.length > 2 ? ")" : ""));
            }
        }

        // regex for robreg with four arguments = robreg.*\)
        squid25FunctionPattern = Pattern.compile("^(.*)[a,A]gePb76.*\\)", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.matches()) {
            String[] agePb76Parts = matcher.group().split(",");
            if (agePb76Parts.length > 1) {
                retVal = retVal.replace(matcher.group(), agePb76Parts[0] + ")");
            }
        }

        // regex for sqWtdAv with four arguments = sqWtdAv.*\)
        squid25FunctionPattern = Pattern.compile("^(.*)[s,S]qWtdAv.*\\)", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.matches()) {
            String[] sqWtdAvParts = matcher.group().split(",");
            if (sqWtdAvParts.length > 1) {
                retVal = retVal.replace(matcher.group(), sqWtdAvParts[0] + ")");
            }
        }

        // regex for sqBiweight with five arguments = sqBiweight.*\)
        squid25FunctionPattern = Pattern.compile("^(.*)[s,S]qBiweight.*\\)", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.matches()) {
            String[] sqBiweightParts = matcher.group().split(",");
            if (sqBiweightParts.length > 1) {
                retVal = retVal.replace(matcher.group(),
                        sqBiweightParts[0] + "," + sqBiweightParts[1] + (sqBiweightParts.length > 2 ? ")" : ""));
            }
        }

        boolean handledConcordiaTW = false;
        // regex for concordiaTW with up to seven arguments = concordiaTW.*\) x, sigma, y sigma , 3 optional
        squid25FunctionPattern = Pattern.compile("^(.*)[c,C]oncordiaTW.*\\)", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.matches()) {
            String[] concordiaTWParts = matcher.group().split(",");
            retVal = retVal.replace(matcher.group(),
                    concordiaTWParts[0] + "," + concordiaTWParts[2] + (concordiaTWParts.length > 3 ? ")" : ""));
            handledConcordiaTW = true;
        }

        if (!handledConcordiaTW) {
            // regex for concordia with up to eight arguments = concordia.*\) x, sigma, y, sigma , rho,  3 optional
            squid25FunctionPattern = Pattern.compile("^(.*)[c,C]oncordia.*\\)", Pattern.CASE_INSENSITIVE);
            matcher = squid25FunctionPattern.matcher(retVal);
            if (matcher.matches()) {
                String[] concordiaParts = matcher.group().split(",");
                retVal = retVal.replace(matcher.group(), concordiaParts[0] + "," + concordiaParts[2] + ","
                        + concordiaParts[4] + (concordiaParts.length > 5 ? ")" : ""));
            }
        }

        // remove "<" and ">" from constants
        squid25FunctionPattern = Pattern.compile("<(.[^>]*)>", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.find()) {
            String constant = matcher.group();
            constant = constant.substring(1, constant.length() - 1);
            retVal = retVal.replace(matcher.group(), constant);
        }

        // remove "/" and " " from expressions that contain letters only
        squid25FunctionPattern = Pattern.compile("\\[\\\"\\D*\\\"\\]", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        if (matcher.find()) {
            String name = matcher.group();
            name = name.replaceAll("/", "").replaceAll(" ", "");
            retVal = retVal.replace(matcher.group(), name);
        }

        // remove leading mulitpliers meant for output tables
        retVal = retVal.replace("1000*", "");
        retVal = retVal.replace("100*", "");

        // do not accept non-numeric constants as being equations - this results from the conflation in Squid2.5 between equations and outputs
        // unless already noted as constant
        if (!taskSquid25.constantNames.contains(retVal)) {
            if (!excelString.contains("(") && !excelString.contains("[")) {
                if (!ShuntingYard.isNumber(excelString)) {
                    retVal = "";
                }
            }
        }

        // do not include calls to error functions of Age as in AgeErPb76 etc
        if (excelString.toUpperCase(Locale.ENGLISH).contains("AGEER")) {
            retVal = "";
        }

        // misc edits
        if (retVal.matches("^.*(?i)corr\\S.*")) {
            if (!retVal.contains("corr.")) {
                retVal = retVal.replace("corr", "cor_");
                if (retVal.contains("204cor")) {
                    retVal = retVal.replace("204cor", "4cor");
                }

                if (retVal.contains("207cor")) {
                    retVal = retVal.replace("207cor", "7cor");
                }

                if (retVal.contains("208cor")) {
                    retVal = retVal.replace("208cor", "8cor");
                }

                if (retVal.matches("^.*\\S(?i)age.*")) {
                    retVal = retVal.replace("Age", "_Age");
                    retVal = retVal.replace("age", "_Age");
                }
            } else {
                if (retVal.matches("^.*\\S(?i)age.*")) {
                    retVal = retVal.replace("Age", " Age");
                    retVal = retVal.replace("age", " Age");
                }
            }
            retVal = retVal.replace("corr 2", "cor_2");
            retVal = retVal.replace("corr2", "cor_2");
        }

        if (retVal.contains("\"4-cor")) {
            retVal = retVal.replace("\"4-cor", "\"4cor");
        }
        if (retVal.contains("\"7-corr")) {
            retVal = retVal.replace("\"7-cor", "\"7cor");
        }
        if (retVal.contains("\"8-corr")) {
            retVal = retVal.replace("\"8-cor", "\"8cor");
        }

        if (retVal.contains("%com206")) {
            retVal = retVal.replace("%com206", COM206PB_PCT);
        }
        if (retVal.contains("%com208")) {
            retVal = retVal.replace("%com208", COM208PB_PCT);
        }

        if (retVal.contains("r_206*/238")) {
            retVal = retVal.replace("r_206*/238", "r_" + R206PB_238U);
        }

        if (retVal.contains("r_207*/206*")) {
            retVal = retVal.replace("r_207*/206*", "r_" + R207PB_206PB);
        }

        if (retVal.contains("r_207*/235")) {
            retVal = retVal.replace("r_207*/235", "r_" + R207PB_235U);
        }

        if (retVal.contains("r_207Pb/206Pb")) {
            retVal = retVal.replace("r_207Pb/206Pb", "r_" + R207PB_206PB);
        }

        if (retVal.contains("r_206Pb/238U")) {
            retVal = retVal.replace("r_206Pb/238U", "r_" + R206PB_238U);
        }

        // finally remove unnecessary ["..."]
        squid25FunctionPattern = Pattern.compile("\\[\\\"([^]]+)\\\"\\]*", Pattern.CASE_INSENSITIVE);
        matcher = squid25FunctionPattern.matcher(retVal);
        while (matcher.find()) {
            String bracketed = matcher.group();
            String unBracketed = bracketed.substring(2, bracketed.length() - 2);
            if (unBracketed.matches("[a-zA-Z0-9_]*[a-zA-Z][a-zA-Z0-9]*")) {
                retVal = retVal.replace(matcher.group(), unBracketed);
            }
        }
        return retVal;
    }

    private static String prepareSquid25ExcelEquationNameForSquid3(String excelString) {
        String retVal = "";

        retVal = excelString.replace("|", "");
        retVal = retVal.replace("(Ma)", "");
        retVal = retVal.replace("/U", "U");
        // remove leading mulitpliers meant for output tables
        retVal = retVal.replace("1000*", "");
        retVal = retVal.replace("100*", "");
        // remove spaces
        retVal = retVal.replace(" ", "");

        // expression customizeradds this space
        retVal = retVal.replace("Age", " Age");

        return retVal;
    }

    /**
     * @return the squidVersion
     */
    public String getSquidVersion() {
        return squidVersion;
    }

    /**
     * @return the squidTaskFileName
     */
    public String getSquidTaskFileName() {
        return squidTaskFileName;
    }

    /**
     * @return the taskType
     */
    public TaskTypeEnum getTaskType() {
        return taskType;
    }

    /**
     * @return the taskName
     */
    public String getTaskName() {
        return taskName;
    }

    /**
     * @return the taskDescription
     */
    public String getTaskDescription() {
        return taskDescription;
    }

    /**
     * @return the nominalMasses
     */
    public List<String> getNominalMasses() {
        return nominalMasses;
    }

    /**
     * @return the ratioNames
     */
    public List<String> getRatioNames() {
        return ratioNames;
    }

    /**
     * @return the backgroundMass
     */
    public String getBackgroundMass() {
        return backgroundMass;
    }

    /**
     *
     * @return
     */
    public String getParentNuclide() {
        return parentNuclide;
    }

    /**
     * @return the directAltPD
     */
    public boolean isDirectAltPD() {
        return directAltPD;
    }

    /**
     *
     * @return
     */
    public String getPrimaryParentElement() {
        return primaryParentElement;
    }

    /**
     * @return the task25Equations
     */
    public List<TaskSquid25Equation> getTask25Equations() {
        return task25Equations;
    }

    /**
     * @return the labName
     */
    public String getLabName() {
        return labName;
    }

    /**
     * @return the authorName
     */
    public String getAuthorName() {
        return authorName;
    }

    /**
     * @return the constantNames
     */
    public List<String> getConstantNames() {
        return constantNames;
    }

    /**
     * @return the constantValues
     */
    public List<String> getConstantValues() {
        return constantValues;
    }

    /**
     * @return the specialSquidFourExpressionsMap
     */
    public Map<String, String> getSpecialSquidFourExpressionsMap() {
        return specialSquidFourExpressionsMap;
    }

}