entries = getDeprecatedPhysicalParamsEntries();
+
+ R03DeprecatedEntry entryFound = entries.stream()
+ .filter(e -> e.getParamName().equals(paramName) && e.getAttributeKey().equals(propertyName)).findFirst()
+ .orElse(null);
+
+ if (entryFound == null) {
+ return getValuesListFromParameterAttribute(getOrEmptyStringFromMap(physParamProperties, propertyName));
+ }
+
+ return getValuesListFromParameterAttribute(entryFound.getOldValue());
+
+ }
+
+ /**
+ * Parses the auxiliary settings file and extracts specification attributes. For
+ * ADJUSED_ERROR, there is special attributes (comment or long_bname) that are
+ * not defined in physical parameters table (R03). THis file also specify a
+ * special value for attribute axis for PRES parameter. This file is versioned
+ * and must but updated with each new version of specification.
+ *
+ *
+ *
+ * This method reads a pipe-delimited configuration file containing auxiliary
+ * settings for pressure axis and adjusted error parameters. Blank lines and
+ * comments are ignored during parsing.
+ *
+ *
+ *
+ * The file format expects lines in the following format: {@code KEY|VALUE}
+ *
+ *
+ *
+ * Supported keys are:
+ *
+ *
+ * - {@code PRES:axis} - Pressure axis identifier
+ * - {@code PRES_ADJUSTED:axis} - Adjusted pressure axis identifier
+ * - {@code ADJUSTED_ERROR:comment} - Comment for adjusted error
+ * - {@code ADJUSTED_ERROR:long_name} - Long name for adjusted error
+ *
+ *
+ *
+ * Default values for {@code presAxis} and {@code presAdjAxis} are set to "Z" if
+ * not specified in the file.
+ *
+ *
+ * @return an {@link AuxilliarySettings} object populated with the parsed values
+ *
+ * @throws FileNotFoundException if the auxiliary settings file does not exist
+ * @throws IOException if the file cannot be read, contains malformed
+ * lines, or contains unrecognized keys
+ *
+ * @see AuxilliarySettings
+ */
+ private AuxilliarySettings parseAuxilliarySettings() throws IOException {
+ // ..initialize special settings
+ AuxilliarySettings auxilliarySettings = new AuxilliarySettings();
+
+ // ..open the file
+ try (InputStream in = SpecIO.getInstance().open(prmFileNameAux);
+ BufferedReader fileReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));) {
+
+ // ..parse the file
+ log.info("parsing \"auxilliary parameter\" file '" + prmFileNameAux + "'");
+
+ // ..read through the file
+ String line;
+ while ((line = fileReader.readLine()) != null) {
+ log.debug("line: '" + line + "'");
+
+ if (pBlankOrComment.matcher(line).matches()) {
+ continue;
}
- if (prmVmax.length() == 0 || prmVmax.equals("-")) {
- prmVmax = ATTR_NOT_ALLOWED;
+
+ // .....parse the line into individual entries.....
+ String parts[] = line.split("\\|");
+ if (parts.length < 2) {
+ // ..it's not a valid parameter definition line
+ throw new IOException("Malformed line in '" + prmFileNameAux + "': '" + line + "'");
}
- if (prmLName.length() == 0 || prmLName.equals("-")) {
- prmVmax = ATTR_IGNORE;
+
+ String key = parts[0].trim();
+ String value = parts[1].trim();
+
+ // ..check for special settings
+ switch (key) {
+ case "PRES:axis":
+ auxilliarySettings.setPresAxis(value);
+ log.debug("pres:axis line : '" + value + "'");
+ break;
+ case "PRES_ADJUSTED:axis":
+ auxilliarySettings.setPresAdjAxis(value);
+ log.debug("pres_adjusted:axis line : '" + value + "'");
+ break;
+ case "ADJUSTED_ERROR:comment":
+ auxilliarySettings.setErrComment(value);
+ log.debug("adjusted_error:comment line : '" + value + "'");
+ break;
+ case "ADJUSTED_ERROR:long_name":
+ auxilliarySettings.setErrLongName(value);
+ log.debug("adjusted_error:long_name line : '" + value + "'");
+ break;
+ default:
+ log.error("Invalid line in '" + prmFileNameAux + "': '" + line + "'");
+ throw new IOException("Invalid line in '" + prmFileNameAux + "': '" + line + "'");
}
- }
- log.debug("parsed: {}|{}|{}|{}|{}|{}|{}|", prm, prmType, prmLName, prmSName, prmUnits, prmVmin, prmVmax,
- prmStatus, prmFill);
+ } // ..end while read(auxilliary param file)
- // ..array of automatic "number" variables
+ } catch (FileNotFoundException e) {
+ log.error("prmFileName '" + prmFileNameAux + "' does not exist");
+ throw e;
+ } catch (IOException e) {
+ log.error("prmFileName '" + prmFileNameAux + "' cannot be read");
+ throw e;
+ }
- String prmList[] = new String[4];
- prmList[0] = prm;
- // ADMT-25 : Always add an underscore to numbering duplicate sensor/parameters
- // variable
- prmList[1] = prm + "_2";
- prmList[2] = prm + "_3";
- prmList[3] = prm + "_4";
+ return auxilliarySettings;
+ }
- // ...LIST-ONLY MODE: grab the param name and continue with the next line
- if (listOnly) {
- for (String prmName : prmList) {
- if (!physParamNameList.contains(prmName)) {// ..new param name
- physParamNameList.add(prmName);
- if (isDeprecated) {
- depParamNameList.add(prmName);
- }
+ /**
+ * Parses the deprecated parameter table and returns only the entries matching
+ * the given version.
+ *
+ *
+ * Lines starting with {@code //} and empty lines are ignored. Each returned
+ * entry represents a (parameter, attribute, deprecated value) triplet that was
+ * valid in a previous version but is no longer accepted in the current
+ * reference version but should only raise a warning and not an error.
+ *
+ * @param path path to the deprecated table file
+ * @param version version filter, e.g. {@code "[3.0]"}
+ * @return list of deprecated entries for the given version, empty if none match
+ * @throws IOException if the file cannot be read
+ */
+ private void parseR03DeprecatedTable(String version) throws IOException {
+ List entries = new ArrayList<>();
- physParamNameList.add(prmName + "_STD");
- physParamNameList.add(prmName + "_MED");
+ try (InputStream in = SpecIO.getInstance().open(r03DepPhysicalParamsTableName);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));) {
- } else { // ..duplicate name is a no, no
- log.error("Duplicate param name '" + prmFileName + "': '" + line + "'");
- file.close();
- throw new IOException("Duplicate param name in '" + prmFileName + "': '" + line + "'");
- }
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.isEmpty() || line.startsWith("//")) {
+ continue;
+ }
+
+ // .....parse the line into individual entries.....
+ String[] c = line.split("\\|");
+ if (c.length < 6) {
+ continue; // not a valid entries as we expect at least 6 columns (deprecation date not
+ // used here)
+ }
+ if (!containsVersion(c[5].trim(), version)) {
+ continue; // we extract only for the current version
}
- continue;
+
+ String attributeKey = c[1].trim();
+ String oldValue = normalizeValue(attributeKey, c[2].trim());
+ String status = c[3].trim();
+ String message = c[4].trim();
+
+ // virtually add the same entries for duplicate param :
+ String[] prmList = buildParamListForDuplicatePhysicalParameters(c[0].trim(),
+ NUMBER_ALLOWED_DUPLICATE_SENSOR);
+ for (String paramName : prmList) {
+ addParamEntries(entries, paramName, attributeKey, oldValue, status, message, version);
+
+ }
+
}
+ }
+ R03DeprecatedEntries = entries;
+ }
+
+ /**
+ * Adds all R03DeprecatedEntry variants for a given parameter name, following
+ * the derivation rules (ADJUSTED, ADJUSTED_ERROR, STD/MED suffixes).
+ */
+ private void addParamEntries(List entries, String paramName, String attributeKey,
+ String oldValue, String status, String message, String version) {
+
+ // Always: base + ADJUSTED
+ List names = new ArrayList<>(List.of(paramName, paramName + "_ADJUSTED"));
- // ..check if there is an "extra dimension"
- // ..at least for now, this is encoded in the data type
- boolean prmExtra = false;
- if (pN_VALUES.matcher(prmComment).matches()) {
- prmExtra = true;
- log.debug("variable with extra dimension: type = '{}'", prmType);
+ // ADJUSTED_ERROR — excluded for min/max/name attributes
+ boolean excludeFromAdjustedError = attributeKey.equals("valid_min") || attributeKey.equals("valid_max")
+ || attributeKey.equals("standard_name")
+ || (version.compareTo("3.1") >= 0 && attributeKey.equals("long_name"));
+
+ if (!excludeFromAdjustedError) {
+ names.add(paramName + "_ADJUSTED_ERROR");
+ }
+
+ // STD & MED family — units and fillValue share the same oldValue
+ if (attributeKey.equals("units") || attributeKey.equals("fillValue")) {
+ names.addAll(List.of(paramName + "_STD", paramName + "_MED", paramName + "_STD_ADJUSTED",
+ paramName + "_MED_ADJUSTED", paramName + "_STD_ADJUSTED_ERROR", paramName + "_MED_ADJUSTED_ERROR"));
+ }
+
+ names.forEach(name -> {
+ entries.add(new R03DeprecatedEntry(name, attributeKey, oldValue, status, message));
+ // special case for "comment" attribute prior to v2.3
+ if (version.compareTo("2.3") < 0 && attributeKey.equals("standard_name")) {
+ entries.add(new R03DeprecatedEntry(name, "comment", oldValue, status, message));
}
+ });
+
+ // long_name — STD/MED variants get a prefixed oldValue
+ if (attributeKey.equals("long_name")) {
+ Map longNameVariants = Map.of(paramName + "_STD", "Standard deviation of " + oldValue,
+ paramName + "_MED", "Median value of " + oldValue, paramName + "_STD_ADJUSTED",
+ "Standard deviation of " + oldValue, paramName + "_MED_ADJUSTED", "Median value of " + oldValue);
+ longNameVariants.forEach((name, derivedValue) -> entries
+ .add(new R03DeprecatedEntry(name, attributeKey, derivedValue, status, message)));
+ }
+ }
- // ..check the data type
- String tmp = prmType;
- switch (prmType) {
- case "NC_DOUBLE":
- prmType = "double";
- break;
- case "NC_FLOAT":
- prmType = "float";
- break;
- case "NC_SHORT":
- prmType = "short";
- break;
+ /**
+ * Normalizes an attribute value for consistent comparison.
+ *
+ *
+ * For numeric attributes ({@code value_min}, {@code value_max},
+ * {@code fillValue}, {@code resolution}), strips any trailing
+ * {@code f}/{@code F} float suffix and parses the result as a double, so that
+ * {@code "-2.f"} and {@code "-2.0"} are considered equal. Non-numeric strings
+ * such as {@code "NC_FILL_SHORT"} or {@code "-"} are returned as-is.
+ *
+ *
+ * For all other attributes, the value is returned trimmed without any
+ * transformation.
+ *
+ * @param attributeKey the attribute name, e.g. {@code "value_min"},
+ * {@code "long_name"}
+ * @param value the raw value to normalize
+ * @return the normalized value, or {@code null} if {@code value} is
+ * {@code null}
+ */
+ private static String normalizeValue(String attributeKey, String value) {
+ if (value == null) {
+ return null;
+ }
+ String v = value.trim();
+
+ if (!NUMERIC_ATTRS.contains(attributeKey)) {
+ return v;
+ }
+
+ if (v.endsWith("f") || v.endsWith("F")) {
+ v = v.substring(0, v.length() - 1);
+ }
+
+ try {
+ return String.valueOf(Double.parseDouble(v));
+ } catch (NumberFormatException e) {
+ return v; // NC_FILL_SHORT, NC_FILL_DOUBLE, "-", etc.
+ }
+ }
+
+ private static boolean containsVersion(String versionField, String version) {
+ // versionField ex: "[2.2,2.3]" or "[3.0]"
+ // Strip brackets then split on comma
+ String stripped = versionField.replaceAll("[\\[\\]\\s]", "");
+ return Arrays.asList(stripped.split(",")).contains(version.replaceAll("[\\[\\]\\s]", ""));
+ }
+
+ /**
+ * For each parameter in R03 table and the related _ (for duplicate
+ * sensor), build the netcdf variable specification : attributes,
+ * dimension and variable name. Also build the related _QC,
+ * _ADJUSTED, _ADJUSTED_QC, _ADJUSTED_ERROR variable.
+ *
+ * @param fileType
+ * @param version
+ * @param prmName : variable name -> parameter name or duplicate sensor
+ * name : TEMP, TEMP_2, PSAL, PSAL_2, etc.
+ * @param dimPQc
+ * @param dimParam
+ * @param errComment
+ * @param errLongName
+ * @param presAxis
+ * @param pres_adjAxis
+ * @param prm : parameter base name. eg. TEMP, PRES, PSAL
+ * @param isDeprecated
+ * @param prmLName
+ * @param prmSName
+ * @param prmUnits
+ * @param prmVmin
+ * @param prmVmax
+ * @param prmFill
+ * @param prmList
+ * @param prmExtra
+ * @param ncDataType
+ * @param keep
+ * @param opt
+ * @param CORE
+ * @param BIO
+ * @throws IOException
+ * @throws R03ParameterException
+ */
+ private void buildParamVariables(ArgoDataFile.FileType fileType, String version, String prmName,
+ ArgoDimension[] dimPQc, ArgoDimension[] dimParam, String errComment, String errLongName, String presAxis,
+ String pres_adjAxis, String prm, boolean isDeprecated, String prmLName, String prmSName, String prmUnits,
+ String prmVmin, String prmVmax, String prmFill, String[] prmList, boolean prmExtra, DataType ncDataType,
+ boolean keep, boolean opt, boolean CORE, boolean BIO) throws IOException, R03ParameterException {
+
+ if (keep) {
+ // build the relevant variable entries
+ log.debug("keeping param: '{}' CORE/BIO {}/{}", prmName, CORE, BIO);
+
+ // add to list of valid parameter names
+ addToPhysParamNameLists(prmName, isDeprecated);
+
+ // create the variable group(s)
+ // see VARIABLE GROUPS documentation at the top
+ String group_qc = prmName + "_QC";
+ String group_adj = prmName + "_ADJUSTED";
+ createVariableGroups(prmName, CORE, BIO, group_qc, group_adj);
+
+ // PRES and Bio-argo files: In bio-argo files,
+ // - only PRES appears
+ // - there is no PROFILE_PRES_QC, PRES_QC, PRES_ADJ_QC, *_ADJ_ERR
+
+ boolean bio_pres = false;
+ if (prm.startsWith("PRES") && pPRESn.matcher(prm).matches()
+ && (fileType == ArgoDataFile.FileType.BIO_PROFILE
+ || fileType == ArgoDataFile.FileType.BIO_TRAJECTORY)) {
+ bio_pres = true;
}
- if (log.isDebugEnabled() && !prmType.equals(tmp)) {
- log.debug("reset prmType from {} to {}", tmp, prmType);
+
+ if (fileType == ArgoDataFile.FileType.PROFILE || fileType == ArgoDataFile.FileType.BIO_PROFILE) {
+
+ /*
+ * Build the parameter structure char PROFILE__QC(N_PROF);
+ * PROFILE__QC:long_name = "Global quality flag of PRES profile";
+ * PROFILE__QC:conventions = "Argo reference table 2a";
+ * PROFILE__QC:_FillValue = " ";
+ *
+ * NOTE: PRES does not have this variable in BIO_PROFILE files
+ */
+ buildProfileParamVariables(prmName, dimPQc, opt, CORE, BIO, group_qc, bio_pres);
+ } // ..end if (PROFILE)
+
+ // ...build the structures....
+ // .. the profile structures are for both and _ADJUSTED
+ buildParamAndParamAdjustedVariables(version, prmName, dimParam, presAxis, pres_adjAxis, prmLName, prmSName,
+ prmUnits, prmVmin, prmVmax, prmFill, prmExtra, ncDataType, opt, CORE, BIO, group_qc, group_adj,
+ bio_pres);
+
+ // if not bio_pres, build the _ADJUSTED_ERROR and STAT ( _STD/MED
+ // and PROFILE__QC(N_PROF)) variables
+ if (!bio_pres) {
+ // ADJUSTED_*
+ buildParamAdjustedErrorVariable(prmName, dimParam, errComment, errLongName, prmLName, prmUnits, prmFill,
+ ncDataType, opt, CORE, BIO, group_adj);
+ // STAT (STAT/MED) variables
+ buildParamStatVariables(fileType, prmName, dimPQc, dimParam, errComment, errLongName, prmLName,
+ prmUnits, prmVmin, prmVmax, prmFill, prmExtra, ncDataType);
+
}
- if (!(prmType.equals("float") || prmType.equals("double") || prmType.equals("short"))) {
- log.error("Invalid data type = '" + line + "'");
- throw new IOException("Invalid data type '" + prmType + "' (" + prmFileName + "; " + nLine + ")");
+ } else {
+ log.debug("not keeping param: '{}' CORE/BIO {}/{}", prmName, CORE, BIO);
+ } // end if (keep)
+
+ }
+
+ /**
+ * STAT variables: Every parameter can have a _STD and/or _MED
+ * group including the *_ADJUSTED variables --- all optional
+ *
+ * The STAT variables are only allowed in the file of the primary parameter core
+ * param STAT only in core files bio param STAT only in bio files
+ *
+ *
+ * @param fileType
+ * @param prmName
+ * @param dimPQc
+ * @param dimParam
+ * @param errComment
+ * @param errLongName
+ * @param prmLName
+ * @param prmUnits
+ * @param prmVmin
+ * @param prmVmax
+ * @param prmFill
+ * @param prmExtra
+ * @param ncDataType
+ */
+ private void buildParamStatVariables(ArgoDataFile.FileType fileType, String prmName, ArgoDimension[] dimPQc,
+ ArgoDimension[] dimParam, String errComment, String errLongName, String prmLName, String prmUnits,
+ String prmVmin, String prmVmax, String prmFill, boolean prmExtra, DataType ncDataType) {
+
+ String STAT[] = { prmName + "_STD", prmName + "_MED" };
+ for (String statNm : STAT) {
+ // ..add to list of valid parameter names
+ physParamNameList.add(statNm);
+ interPhysParam.add(statNm); // they are "intermediate parameters"
+
+ // ..create the variable group
+ // ..each of these are there own group
+ String stat_qc = statNm + "_QC";
+ String stat_adj = statNm + "_ADJUSTED";
+ if (!groupMembers.containsKey(statNm)) { // ..new group - init
+ groupMembers.put(stat_qc, new HashSet());
+ log.debug("create group: '{}'", statNm);
+ groupMembers.put(stat_adj, new HashSet());
+ log.debug("create group: '{}_ADJUSTED'", statNm);
}
- DataType ncDataType = DataType.getType(prmType);
+ /*
+ * ***** Apr 2015 Users of the STAT variables are not including PROFILE_*_QC So
+ * don't allow them at all until there is some outcry
+ *
+ * ***** Update: Apr 2022 Handle these as "intermediate parameters"
+ */
- // ..check for symbolic NETCDF fill values
+ if (fileType == ArgoDataFile.FileType.PROFILE || fileType == ArgoDataFile.FileType.BIO_PROFILE) {
- if (prmFill.startsWith("NC_FILL_")) {
- tmp = prmFill;
- prmFill = NC_FILL_TYPES.get(tmp);
+ buidProfileStatQcVariable(dimPQc, statNm, stat_qc);
+ } // end if (PROFILE)
- if (prmFill == null) {
- log.debug("Invalid NC_FILL_: '" + tmp + "' in line '" + line + "'");
- throw new IOException("Invalid NC_FILL_: '" + tmp + "' (" + prmFileName + "; " + nLine + ")");
- }
+ // build the structures....
+ // the profile structures are for both and _ADJUSTED
+ String S[] = new String[] { statNm, statNm + "_ADJUSTED" };
+ for (String v : S) {
- log.debug("Changed fill-value from {} to {}", tmp, prmFill);
- }
+ buildStatAndStatAdjustedVariables(dimParam, prmLName, prmUnits, prmVmin, prmVmax, prmFill, prmExtra,
+ ncDataType, statNm, stat_qc, stat_adj, v);
+ } // ..end for v : , _ADJUSTED
+
+ // build _ADJUSTED_ERROR variable
+ buildStatAdjustedErrorVariable(dimParam, errComment, errLongName, prmLName, prmUnits, prmFill, ncDataType,
+ statNm, stat_adj);
+ } // ..end for _STD, _MED
+ }
+
+ /**
+ * Build the parameter structure _ADJUSTED_ERROR(N_PROF,
+ * N_LEVELS); _ADJUSTED_ERROR:long_name = "";
+ * _ADJUSTED_ERROR:_FillValue = ;
+ * _ADJUSTED_ERROR:units = "";
+ * _ADJUSTED_ERROR:comment = "Contains the error on the \ adjusted values
+ * as determined by the delayed mode QC process.";
+ * _ADJUSTED_ERROR:C_format = ATTR_IGNORE_VALUE;
+ * _ADJUSTED_ERROR:FORTRAN_format = ATTR_IGNORE_VALUE;
+ * _ADJUSTED_ERROR:resolution = ATTR_IGNORE_VALUE;
+ *
+ * @param dimParam
+ * @param errComment
+ * @param errLongName
+ * @param prmLName
+ * @param prmUnits
+ * @param prmFill
+ * @param ncDataType
+ * @param statNm
+ * @param stat_adj
+ */
+ private void buildStatAdjustedErrorVariable(ArgoDimension[] dimParam, String errComment, String errLongName,
+ String prmLName, String prmUnits, String prmFill, DataType ncDataType, String statNm, String stat_adj) {
+
+ String varNm = new String(statNm + "_ADJUSTED_ERROR");
+
+ String longName = (errLongName == null ? prmLName : errLongName);
+
+ // create variable
+ ArgoVariable aVar = createPhysParamArgoVariable(statNm, dimParam, varNm, ncDataType, longName, prmFill, "",
+ prmUnits, "", "", ATTR_IGNORE_VALUE, "", errComment, ATTR_IGNORE_VALUE, ATTR_IGNORE_VALUE);
+
+ // add variable in lists and group :
+ varHash.put(varNm, aVar);
+ optVar.add(varNm);
+ physParamVarList.add(varNm);
+
+ varGroup.put(varNm, stat_adj);
+ groupMembers.get(stat_adj).add(varNm); // add to the ADJUSTED group
+
+ log.debug("added: '{}': opt '{}' ; primary '{}'; 'member '{}'", varNm, true, stat_adj, stat_adj);
+ }
+
+ /**
+ * Build the parameter STAT structure Profile: (N_PROF,
+ * N_LEVELS); -or- (N_PROF, N_LEVELS,_extra_) Trajectory:
+ * (N_MEASUREMENT); -or- (N_MEASUREMENT,
+ * _extra_) :long_name = ""; //:standard_name =
+ * ""; :_FillValue = ; :units =
+ * ""; :valid_min = ; :valid_max =
+ * ; :comment = ""; (version-specific)
+ * :C_format = ATTR_IGNORE_VALUE; //..means ignore setting :FORTRAN_format
+ * = ATTR_IGNORE_VALUE; //..means ignore setting :resolution =
+ * ATTR_IGNORE_VALUE; :comment_on_resolution = ATTR_IGNORE; ///..means ignore
+ * entirely only in v3.1 and beyond (but technically would be allowed in earlier
+ * versions if it showed up
+ *
+ *
+ * where = , _ADJUSTED
+ *
+ * @param dimParam
+ * @param prmLName
+ * @param prmUnits
+ * @param prmVmin
+ * @param prmVmax
+ * @param prmFill
+ * @param prmExtra
+ * @param ncDataType
+ * @param statNm
+ * @param stat_qc
+ * @param stat_adj
+ * @param v
+ */
+ private void buildStatAndStatAdjustedVariables(ArgoDimension[] dimParam, String prmLName, String prmUnits,
+ String prmVmin, String prmVmax, String prmFill, boolean prmExtra, DataType ncDataType, String statNm,
+ String stat_qc, String stat_adj, String v) {
+
+ // build the long_name depending on _STAT or _MED :
+ StringBuilder tmpLName;
+ if (statNm.endsWith("_STD")) {
+ tmpLName = new StringBuilder("Standard deviation of ");
+ } else {
+ tmpLName = new StringBuilder("Median value of ");
+ }
+ tmpLName.append(prmLName.substring(0, 1).toLowerCase()).append(prmLName.substring(1));
+
+ // build the variable depending on _STAT or _MED :
+ ArgoVariable aVar;
+ if (statNm.endsWith("_STD")) {
+ aVar = createPhysParamArgoVariable(statNm, dimParam, v, ncDataType, tmpLName.toString(), prmFill, "",
+ prmUnits, "", "", ATTR_IGNORE, ATTR_IGNORE + "resolution is unknown", "", ATTR_IGNORE_VALUE,
+ ATTR_IGNORE_VALUE);
+ } else {
+ // _MED
+ aVar = createPhysParamArgoVariable(statNm, dimParam, v, ncDataType, tmpLName.toString(), prmFill, "",
+ prmUnits, prmVmin, prmVmax, ATTR_IGNORE, ATTR_IGNORE + "resolution is unknown", "",
+ ATTR_IGNORE_VALUE, ATTR_IGNORE_VALUE);
+ }
+ // extra dims authorized ?
+ if (prmExtra) {
+ aVar.setHaveExtraDimension();
+ }
+
+ // add to physParamList :
+ varHash.put(v, aVar);
+ physParamVarList.add(v);
+
+ // ..add to the appropriate groups
+ String group;
+ if (v.endsWith("_ADJUSTED")) {
+ group = stat_adj;
+ varGroup.put(v, stat_adj);
+ groupMembers.get(stat_adj).add(v); // ..add to the appropriate group
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", v, true, stat_adj, stat_adj);
+
+ } else {
+ group = stat_qc;
+ varGroup.put(v, stat_qc);
+ groupMembers.get(stat_adj).add(v);
+ groupMembers.get(stat_qc).add(v);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", v, true, "", stat_adj);
+ }
+
+ optVar.add(v);
+
+ /*
+ * Build the parameter structure char _QC(N_PROF, N_LEVELS); _QC:long_name
+ * = "quality flag"; _QC:conventions = "Argo reference table 2";
+ * _QC:_FillValue = " ";
+ *
+ * where = , _ADJUSTED
+ */
- // ..check the PrmCat -- "c" = core, "b" = bio, "ic/ib" = intermediate -> core,
- // bio
- if (!(prmCategory.equals("c") || prmCategory.equals("b") || prmCategory.equals("ic")
- || prmCategory.equals("ib"))) {
- log.debug("Invalid category '" + prmCategory + "' in line '" + line + "'");
- throw new IOException("Invalid category '" + prmCategory + "' (" + prmFileName + "; " + nLine + ")");
+ String varNm = new String(v + "_QC");
+ aVar = createPhysParamArgoVariable(statNm, dimParam, varNm, DataType.CHAR, prmQcLName, fillValueBLANK,
+ prmQcConventions, "", "", "", "", "", "", "", "");
+
+ // group = v+"_QC";
+ varHash.put(varNm, aVar);
+ groupMembers.get(group).add(varNm); // ..add to the prmName group of variables
+ physParamVarList.add(varNm);
+
+ log.debug("variable added: '{}' (group '{}')", varNm, group);
+
+ // ..add to options
+ varGroup.put(varNm, group);
+ optVar.add(varNm);
+ log.debug("option added: '{}' (group '{})", varNm, group);
+ }
+
+ /**
+ *
+ * Build the parameter structure char PROFILE__QC(N_PROF);
+ * PROFILE__QC:long_name = "Global quality flag of profile";
+ * PROFILE__QC:conventions = "Argo reference table 2a";
+ * PROFILE__QC:_FillValue = " ";
+ *
+ * where = _STD, _MED
+ *
+ * @param dimPQc
+ * @param statNm
+ * @param stat_qc
+ */
+ private void buidProfileStatQcVariable(ArgoDimension[] dimPQc, String statNm, String stat_qc) {
+ String varNm = new String("PROFILE_" + statNm + "_QC");
+
+ ArgoVariable aVar = createPhysParamArgoVariable(statNm, dimPQc, varNm, DataType.CHAR,
+ prfQcLName + statNm + " profile", fillValueBLANK, prfQcConventions, "", "", "", "", "", "", "", "");
+
+ varHash.put(varNm, aVar);
+ physParamVarList.add(varNm);
+
+ // add to optionanls variables group
+ varGroup.put(varNm, stat_qc);
+ groupMembers.get(stat_qc).add(varNm);
+ optVar.add(varNm);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", varNm, true, stat_qc, stat_qc);
+ }
+
+ /**
+ * Build the parameter structure Profile
+ * _ADJUSTED_ERROR(N_PROF, N_LEVELS); Trajectory
+ * _ADJUSTED_ERROR(N_MEASUREMENT);
+ *
+ * _ADJUSTED_ERROR:long_name = "";
+ * _ADJUSTED_ERROR:_FillValue = _ADJUSTED_ERROR:units = "_ADJUSTED_ERROR:comment = "Contains the error on the \ adjusted values
+ * as determined by the delayed mode QC process.";
+ * _ADJUSTED_ERROR:C_format = "%7.1f";
+ * _ADJUSTED_ERROR:FORTRAN_format = "F7.1";
+ * _ADJUSTED_ERROR:resolution = 0.1f;
+ *
+ * @param prmName
+ * @param dimParam
+ * @param errComment
+ * @param errLongName
+ * @param prmLName
+ * @param prmUnits
+ * @param prmFill
+ * @param ncDataType
+ * @param opt
+ * @param CORE
+ * @param BIO
+ * @param group_adj
+ */
+ private void buildParamAdjustedErrorVariable(String prmName, ArgoDimension[] dimParam, String errComment,
+ String errLongName, String prmLName, String prmUnits, String prmFill, DataType ncDataType, boolean opt,
+ boolean CORE, boolean BIO, String group_adj) {
+ String varNm;
+ ArgoVariable aVar;
+ varNm = new String(prmName + "_ADJUSTED_ERROR");
+ // aVar = new ArgoVariable(varNm, ncDataType, dimParam, prmName);
+ aVar = createPhysParamArgoVariable(prmName, dimParam, varNm, ncDataType,
+ (errLongName == null ? prmLName : errLongName), prmFill, "", prmUnits, "", "", ATTR_IGNORE + prmFill,
+ "", errComment, ATTR_IGNORE_VALUE + "%15.4f", ATTR_IGNORE_VALUE + "F15.4");
+
+// createPhysParamArgoVariable(String prmName, ArgoDimension[] dimPQc, String varNm,
+// DataType dataType, String prmLongName, String prmFillValue, String prmConventions, String prmUnits,
+// String prmVmin, String prmVmax, String prmResolution, String resolutionComment, String errComment)
+
+ // addAttr(aVar, long_name, (errLongName == null ? prmLName : errLongName),
+ // DataType.STRING);
+
+ // addAttr(aVar, fillValue, prmFill, ncDataType);
+ // addAttr(aVar, units, prmUnits, DataType.STRING);
+ // addAttr(aVar, comment, errComment, DataType.STRING);
+// addAttr(aVar, c_format, ATTR_IGNORE_VALUE + "%15.4f", DataType.STRING);
+// addAttr(aVar, fortran_format, ATTR_IGNORE_VALUE + "F15.4", DataType.STRING);
+ // addAttr(aVar, resolution, ATTR_IGNORE + prmFill, ncDataType);
+
+ varHash.put(varNm, aVar);
+ physParamVarList.add(varNm);
+
+ // ..add to group -- see VARIABLE GROUPS above
+
+ String group;
+ if (CORE || BIO) {
+ group = prmName;
+
+ } else { // ..an i-parameter
+ group = group_adj;
+ }
+
+ varGroup.put(varNm, group);
+ groupMembers.get(group).add(varNm);
+ log.debug("added: '{}'; opt '{}'; primary group'{}'; member '{}'", varNm, opt, group, group);
+
+ if (opt) {
+ // ..add to optional variables
+ optVar.add(varNm);
+ }
+ }
+
+ /**
+ * Build the parameter structure Profile:
+ *
+ * (N_PROF, N_LEVELS) -or-
+ *
+ * (N_PROF, N_LEVELS,_extra_)
+ *
+ * Trajectory:
+ *
+ * (N_MEASUREMENT); -or-
+ *
+ * (N_MEASUREMENT, _extra_)
+ *
+ * Attributes:
+ *
+ * :long_name = "";
+ *
+ * :standard_name = "";
+ *
+ * :_FillValue = ;
+ *
+ * :units = "";
+ *
+ * :valid_min = ;
+ *
+ * :valid_max = ;
+ *
+ * :comment = ""; (version-specific)
+ *
+ * :C_format = ATTR_IGNORE_VALUE; //..means ignore setting
+ *
+ * :FORTRAN_format = ATTR_IGNORE_VALUE; //..means ignore setting
+ *
+ * :resolution = ATTR_IGNORE_VALUE;
+ *
+ * :comment_on_resolution = ATTR_IGNORE; ///..means ignore entirely only in v3.1
+ * and beyond (but technically would be allowed in earlier versions if it showed
+ * up
+ *
+ * where
+ *
+ * = , _ADJUSTED
+ *
+ * if
+ *
+ * = PRES or PRES_ADJUSTED, add
+ *
+ * :axis = "Z"
+ *
+ * @param version
+ * @param prmName
+ * @param dimParam
+ * @param presAxis
+ * @param pres_adjAxis
+ * @param prmLName
+ * @param prmSName
+ * @param prmUnits
+ * @param prmVmin
+ * @param prmVmax
+ * @param prmFill
+ * @param prmExtra
+ * @param ncDataType
+ * @param opt
+ * @param CORE
+ * @param BIO
+ * @param group_qc
+ * @param group_adj
+ * @param bio_pres
+ */
+ private void buildParamAndParamAdjustedVariables(String version, String prmName, ArgoDimension[] dimParam,
+ String presAxis, String pres_adjAxis, String prmLName, String prmSName, String prmUnits, String prmVmin,
+ String prmVmax, String prmFill, boolean prmExtra, DataType ncDataType, boolean opt, boolean CORE,
+ boolean BIO, String group_qc, String group_adj, boolean bio_pres) {
+ String varNm;
+ ArgoVariable aVar;
+ String P[] = { prmName, prmName + "_ADJUSTED" };
+
+ for (String v : P) {
+
+ log.debug("...working on: {}", v);
+
+ // aVar = new ArgoVariable(v, ncDataType, dimParam, prmName);
+ aVar = createPhysParamArgoVariable(prmName, dimParam, v, ncDataType, prmLName, prmFill, "", prmUnits,
+ prmVmin, prmVmax, ATTR_IGNORE + "99999.", ATTR_IGNORE + "resolution is unknown", "", "", "");
+// addAttr(aVar, long_name, prmLName, DataType.STRING);
+// addAttr(aVar, fillValue, prmFill, ncDataType);
+// addAttr(aVar, units, prmUnits, DataType.STRING);
+// addAttr(aVar, valid_min, prmVmin, ncDataType);
+// addAttr(aVar, valid_max, prmVmax, ncDataType);
+// addAttr(aVar, resolution, ATTR_IGNORE + "99999.", ncDataType);
+// addAttr(aVar, comment_on_resolution, ATTR_IGNORE + "resolution is unknown", DataType.STRING);
+
+ // add conditionals attributes :
+ if (version.compareTo("2.3") < 0) {
+ addAttr(aVar, comment, prmSName, DataType.STRING);
+ } else {
+ addAttr(aVar, standard_name, prmSName, DataType.STRING);
+ }
+ if (v.startsWith("PRES")) {
+ addAttr(aVar, c_format, ATTR_IGNORE_VALUE + "%15.1f", DataType.STRING);
+ addAttr(aVar, fortran_format, ATTR_IGNORE_VALUE + "F15.1", DataType.STRING);
+ } else {
+ addAttr(aVar, c_format, ATTR_IGNORE_VALUE + "%15.3f", DataType.STRING);
+ addAttr(aVar, fortran_format, ATTR_IGNORE_VALUE + "F15.3", DataType.STRING);
}
- // ..decide if this parameter is in this type of file
+ if (v.equals("PRES")) {
+ // ========
+ // REQ_0037
+ // ========
+ addAttr(aVar, axis, presAxis, DataType.STRING);
+ } else if (v.equals("PRES_ADJUSTED")) {
+ addAttr(aVar, axis, pres_adjAxis, DataType.STRING);
+ }
- boolean keep = false;
- boolean opt = true;
- boolean CORE = false;
- boolean BIO = false;
+ // if an extra dimension is described in param attributes:
+ if (prmExtra) {
+ aVar.setHaveExtraDimension();
+ }
- // ..check for a valid file type and decide if it's a keeper
- if (prmCategory.equals("c")) {
- CORE = true;
- BIO = false;
+ varHash.put(v, aVar);
+ physParamVarList.add(v);
- if (prm.startsWith("PRES") && pPRESn.matcher(prm).matches()) {
- // ..keep PRES / PRESn in all cases
- opt = false;
- keep = true;
+ // ..add to group(s) -- see VARIABLE GROUPS above
+ if (CORE || BIO) {
+ varGroup.put(v, prmName);
+ groupMembers.get(prmName).add(v);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", v, opt, prmName, prmName);
- // ..treat PRES/PRESn like any other bio-parameter in Bio- files
- if (isBioProf || isOldBioTraj) {
- CORE = false;
- }
+ } else {
+ // ..an i-parameter
+ // .. has no primary group and belongs to _qc and _adj groups
+ // .._ADJ has primary and belongs to only _adj group
+ // ..(ADMT-16: can no longer exist by itself)
+ // ==========
+ // CHECK_0076
+ // ==========
+
+ if (v.endsWith("_ADJUSTED")) {
+ varGroup.put(v, group_adj);
+ groupMembers.get(group_adj).add(v);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", v, opt, group_adj, group_adj);
- } else if (isCoreProf || isTraj || isOldCoreTraj) {
- // ..keep "c" parameters for core and traj (> v3.1) files
- keep = true;
- if (prm.equals("TEMP") && fileType == ArgoDataFile.FileType.PROFILE) {
- opt = false;
- }
+ } else {
+ varGroup.put(v, group_qc);
+ groupMembers.get(group_adj).add(v);
+ groupMembers.get(group_qc).add(v);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'/'{}'", v, opt, "", group_qc, group_adj);
}
+ }
- } else if (prmCategory.equals("ic")) {
- CORE = false;
- BIO = false;
+ if (opt) {
+ // ..add to optional variables
+ optVar.add(v);
+ }
- if (isCoreProf || isTraj || isOldCoreTraj) {
- // ..keep "c" and "ic" parameters for core and traj (> v3.1) files
- keep = true;
- }
+ /*
+ * Build the parameter structure Profile char
_QC(N_PROF, N_LEVELS);
+ * Trajectory char
_QC(N_MEASUREMENT);
+ *
+ *
_QC:long_name = "quality flag";
_QC:conventions =
+ * "Argo reference table 2";
_QC:_FillValue = " ";
+ *
+ * where
= , _ADJUSTED
+ *
+ * Don't put PRES_QC in bio-Argo file. (==> bio_pres = true)
+ */
+
+ if (!bio_pres) {
+ // build the *_QC and _ADJUSTED_QC variables
+ varNm = new String(v + "_QC");
+ aVar = createPhysParamArgoVariable(prmName, dimParam, varNm, DataType.CHAR, prmQcLName, fillValueBLANK,
+ prmQcConventions, "", "", "", "", "", "", "", "");
+// aVar = new ArgoVariable(varNm, DataType.CHAR, dimParam, prmName);
+// addAttr(aVar, long_name, prmQcLName, DataType.STRING);
+// addAttr(aVar, conventions, prmQcConventions, DataType.STRING);
+// addAttr(aVar, fillValue, fillValueBLANK, DataType.STRING);
+
+ varHash.put(varNm, aVar);
+ physParamVarList.add(varNm);
+
+ // ..add to group -- see VARIABLE GROUPS above
+ if (CORE || BIO) {
+ varGroup.put(varNm, prmName);
+ groupMembers.get(prmName).add(varNm);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", varNm, opt, prmName, prmName);
- } else if (prmCategory.equals("b")) {
- CORE = false;
- BIO = true;
+ } else {
+ String group;
+ if (v.endsWith("_ADJUSTED")) {
+ group = group_adj;
+ } else {
+ group = group_qc;
+ }
- if (isBioProf || isTraj || isOldBioTraj) {
- // ..keep "b" parameters for Bio-Argo and traj (> v3.1) files
- keep = true;
+ varGroup.put(varNm, group);
+ groupMembers.get(group).add(varNm);
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}')", varNm, opt, group, group);
}
- } else if (prmCategory.equals("ib")) {
- CORE = false;
- BIO = false;
-
- if (isBioProf || isTraj || isOldBioTraj) {
- // ..keep "ib" parameters for Bio-Argo and traj (> v3.1) files
- keep = true;
+ if (opt) {
+ // ..add to optional variables
+ optVar.add(varNm);
}
} else {
- log.debug("Invalid param category (c,b,ic,ib) '" + prmCategory + "' in line '" + line + "'");
- throw new IOException("Invalid parameter category (c,b,i) '" + prmCategory + "' (" + prmFileName + "; "
- + nLine + ")");
+ log.debug("skip: '{}_QC' (bio_pres == true)", v);
}
- // ..for each entry, automatically make * variables too
- for (String prmName : prmList) {
+ /*
+ * Do not put PRES_ADJUSTED in bio-argo file -- bio_pres = true ==> =
+ * PRES && this is a bio-profile file
+ */
+ if (bio_pres) {
+ log.debug("skip PRES_ADJUSTED: (bio_pres == true)");
+ break;
+ }
+ }
+ }
- if (keep) {
- // ..build the relevant variable entries
- log.debug("keeping param: '{}' CORE/BIO {}/{}", prmName, CORE, BIO);
+ /**
+ *
+ * Build the parameter structure char PROFILE__QC(N_PROF);
+ * PROFILE__QC:long_name = "Global quality flag of PRES profile";
+ * PROFILE__QC:conventions = "Argo reference table 2a";
+ * PROFILE__QC:_FillValue = " ";
+ *
+ * NOTE: PRES does not have this variable in BIO_PROFILE files
+ *
+ * @param prmName
+ * @param dimPQc
+ * @param opt
+ * @param CORE
+ * @param BIO
+ * @param group_qc
+ * @param bio_pres
+ */
+ private void buildProfileParamVariables(String prmName, ArgoDimension[] dimPQc, boolean opt, boolean CORE,
+ boolean BIO, String group_qc, boolean bio_pres) {
+ String varNm;
+ ArgoVariable aVar;
+ if (!bio_pres) {
+ varNm = new String("PROFILE_" + prmName + "_QC");
+ aVar = createPhysParamArgoVariable(prmName, dimPQc, varNm, DataType.CHAR, prfQcLName + prmName + " profile",
+ fillValueBLANK, prfQcConventions, "", "", "", "", "", "", "", "");
+
+ varHash.put(varNm, aVar);
+ physParamVarList.add(varNm);
+
+ // ..add to groups ... see VARIABLE GROUPS above
+
+ String group;
+ if (CORE || BIO) {
+ group = prmName;
+
+ } else { // ..this is an intermediate parameter
+ group = group_qc;
+ }
- // ..add to list of valid parameter names
- if (!physParamNameList.contains(prmName)) {// ..new param name
- physParamNameList.add(prmName);
- if (isDeprecated) {
- depParamNameList.add(prmName);
- }
+ varGroup.put(varNm, group);
+ groupMembers.get(group).add(varNm);
- } else { // ..duplicate name is a no, no
- log.error("Duplicate param name (line {}) '{}'", nLine, prmName);
- throw new IOException(
- "Duplicate param name in '" + prmFileName + "' (line " + nLine + "): '" + line + "'");
- }
+ if (opt) {
+ // ..add to optional variables
+ optVar.add(varNm);
+ }
- // ..create the variable group(s)
- // -- see VARIABLE GROUPS documentation at the top
+ log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", varNm, opt, group, group);
- String group_qc = prmName + "_QC";
- String group_adj = prmName + "_ADJUSTED";
+ } else {
+ log.debug("skip: 'PROFILE_{}_QC' (bio_pres = true)", prmName);
+ }
+ }
- if (CORE || BIO) { // ..a "full parameter"
- if (!groupMembers.containsKey(prmName)) { // ..new group - init
- groupMembers.put(prmName, new HashSet());
- log.debug("create group: '{}'", prmName);
- }
+ private ArgoVariable createPhysParamArgoVariable(String prmName, ArgoDimension[] dimPQc, String varNm,
+ DataType dataType, String prmLongName, String prmFillValue, String prmConventions, String prmUnits,
+ String prmVmin, String prmVmax, String prmResolution, String resolutionComment, String errComment,
+ String paramCformat, String paramFortranFormat) {
+ ArgoVariable aVar;
+ aVar = new ArgoVariable(varNm, dataType, dimPQc, prmName);
+ // Mandatory attributes
+ addAttr(aVar, long_name, prmLongName, DataType.STRING);
+ DataType fillValueType = dataType.equals(DataType.CHAR) ? DataType.STRING : dataType;
+ addAttr(aVar, fillValue, prmFillValue, fillValueType);
+
+ // optionnals attributes
+ addAttrIfNotEmpty(aVar, conventions, prmConventions, DataType.STRING);
+ addAttrIfNotEmpty(aVar, units, prmUnits, DataType.STRING);
+ addAttrIfNotEmpty(aVar, valid_min, prmVmin, dataType);
+ addAttrIfNotEmpty(aVar, valid_max, prmVmax, dataType);
+ addAttrIfNotEmpty(aVar, resolution, prmResolution, dataType);
+ addAttrIfNotEmpty(aVar, comment_on_resolution, resolutionComment, DataType.STRING);
+ addAttrIfNotEmpty(aVar, comment, errComment, DataType.STRING);
+ addAttrIfNotEmpty(aVar, c_format, paramCformat, DataType.STRING);
+ addAttrIfNotEmpty(aVar, fortran_format, paramFortranFormat, DataType.STRING);
+
+ return aVar;
+ }
- } else { // ..implies an i-parameter
- interPhysParam.add(prmName);
- log.debug("add intermediate variable '{}'", prmName);
+ /**
+ * Adds an attribute to the variable only if the value is not null or empty.
+ *
+ * @param var The ArgoVariable to add the attribute to
+ * @param attrName Attribute name
+ * @param value Attribute value
+ * @param dataType Data type of the attribute
+ */
+ private void addAttrIfNotEmpty(ArgoVariable var, String attrName, String value, DataType dataType) {
+ if (value != null && !value.isEmpty()) {
+ addAttr(var, attrName, value, dataType);
+ }
+ }
- // ..make the _qc group
- if (!groupMembers.containsKey(group_qc)) { // ..new group - init
- groupMembers.put(group_qc, new HashSet());
- log.debug("create group: '{}'", group_qc);
- }
+ private void addToPhysParamNameLists(String prmName, boolean isDeprecated) throws R03ParameterException {
+ if (!physParamNameList.contains(prmName)) {// ..new param name
+ physParamNameList.add(prmName);
+ if (isDeprecated) {
+ depParamNameList.add(prmName);
+ }
- // ..make the _adj group
- if (!groupMembers.containsKey(group_adj)) { // ..new group - init
- groupMembers.put(group_adj, new HashSet());
- log.debug("create group: '{}'", group_adj);
- }
- }
+ } else { // ..duplicate name is a no, no
+ throw new R03ParameterException("Duplicate param name (NVS R03) 'prmName'");
+ }
+ }
- // ..PRES and Bio-argo files: In bio-argo files,
- // .. - only PRES appears
- // .. - there is no PROFILE_PRES_QC, PRES_QC, PRES_ADJ_QC, *_ADJ_ERR
+ private void createVariableGroups(String prmName, boolean CORE, boolean BIO, String group_qc, String group_adj) {
+ // ==========
+ // CHECK_0295
+ // ==========
+ // phase of building variable group in fonction of core/bgc and intermediate
+ // physical parameter is important for te format check and the expected presence
+ // of _ADJUSTED, _ADJUSTED_QC, _ADJUSTED_ERROR
+ if (CORE || BIO) { // ..a "full parameter"
+ if (!groupMembers.containsKey(prmName)) { // ..new group - init
+ groupMembers.put(prmName, new HashSet());
+ log.debug("create group: '{}'", prmName);
+ }
- boolean bio_pres = false;
- if (prm.startsWith("PRES") && pPRESn.matcher(prm).matches()
- && (fileType == ArgoDataFile.FileType.BIO_PROFILE
- || fileType == ArgoDataFile.FileType.BIO_TRAJECTORY)) {
- bio_pres = true;
- }
+ } else { // ..implies an i-parameter
+ interPhysParam.add(prmName);
+ log.debug("add intermediate variable '{}'", prmName);
- String varNm;
- ArgoVariable aVar;
-
- if (fileType == ArgoDataFile.FileType.PROFILE || fileType == ArgoDataFile.FileType.BIO_PROFILE) {
-
- /*
- * Build the parameter structure char PROFILE__QC(N_PROF);
- * PROFILE__QC:long_name = "Global quality flag of PRES profile";
- * PROFILE__QC:conventions = "Argo reference table 2a";
- * PROFILE__QC:_FillValue = " ";
- *
- * NOTE: PRES does not have this variable in BIO_PROFILE files
- */
- if (!bio_pres) {
- varNm = new String("PROFILE_" + prmName + "_QC");
- aVar = new ArgoVariable(varNm, DataType.CHAR, dimPQc, prmName);
- addAttr(aVar, long_name, prfQcLName + prmName + " profile", DataType.STRING);
- addAttr(aVar, conventions, prfQcConventions, DataType.STRING);
- addAttr(aVar, fillValue, fillValueBLANK, DataType.STRING);
-
- varHash.put(varNm, aVar);
- physParamVarList.add(varNm);
-
- // ..add to groups ... see VARIABLE GROUPS above
-
- String group;
- if (CORE || BIO) {
- group = prmName;
-
- } else { // ..this is an intermediate parameter
- group = group_qc;
- }
+ // ..make the _qc group
+ if (!groupMembers.containsKey(group_qc)) { // ..new group - init
+ groupMembers.put(group_qc, new HashSet());
+ log.debug("create group: '{}'", group_qc);
+ }
- varGroup.put(varNm, group);
- groupMembers.get(group).add(varNm);
+ // ..make the _adj group
+ if (!groupMembers.containsKey(group_adj)) { // ..new group - init
+ groupMembers.put(group_adj, new HashSet());
+ log.debug("create group: '{}'", group_adj);
+ }
+ }
+ }
- if (opt) {
- // ..add to optional variables
- optVar.add(varNm);
- }
+ /**
+ * check for symbolic NETCDF fill values. If prmFill start with NC_FILL, replace
+ * it with the right NC_FILL_TYPE value if key prmFill exists in the map.
+ *
+ * @param prm (String) parameter name needed for error message.
+ * @param prmFill (String) extracted (with NvsDefintionParser) Fill_Value from
+ * NVS table definition's field.
+ * @return
+ * @throws IOException
+ * @throws R03ParameterException
+ */
+ private String checkAndRepacleWithNcFillTypes(String prm, String prmFill) throws R03ParameterException {
+ if (prmFill.startsWith("NC_FILL_")) {
+ String tmp = prmFill;
+ prmFill = NC_FILL_TYPES.get(tmp);
+
+ if (prmFill == null) {
+ throw new R03ParameterException("Invalid NC_FILL_: '" + prmFill + "' (NVS R03, parameter : " + prm
+ + "). This parameter will be ignored in specification definition.");
+ }
- log.debug("added: '{}'; opt '{}'; primary '{}'; member '{}'", varNm, opt, group, group);
+ log.debug("Changed fill-value from {} to {}", tmp, prmFill);
+ }
+ return prmFill;
+ }
- } else {
- log.debug("skip: 'PROFILE_{}_QC' (bio_pres = true)", prmName);
- }
- } // ..end if (PROFILE)
-
- // ...build the structures....
- // .. the profile structures are for both and _ADJUSTED
-
- String P[] = { prmName, prmName + "_ADJUSTED" };
-
- for (String v : P) {
- /*
- * Build the parameter structure Profile: (N_PROF, N_LEVELS)
- * -or-