CRDConfiguration.java

  1. /* Copyright 2002-2024 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.files.ilrs;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Collections;
  21. import java.util.Hashtable;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Set;
  25. import java.util.regex.Pattern;

  26. /**
  27.  * Container for Consolidated laser ranging Data Format (CDR) configuration records.
  28.  * @author Bryan Cazabonne
  29.  * @author Rongwang Li
  30.  * @since 10.3
  31.  */
  32. public class CRDConfiguration {

  33.     /** Dict of configuration record. **/
  34.     private Map<String, BaseConfiguration> mapConfigurationRecords;

  35.     /** List of system configuration. **/
  36.     private List<SystemConfiguration> systemConfigurationRecords;

  37.     /**
  38.      * Constructor.
  39.      */
  40.     public CRDConfiguration() {
  41.         systemConfigurationRecords = new ArrayList<>();
  42.         mapConfigurationRecords = new Hashtable<>();
  43.     }

  44.     /**
  45.      * Get the system configuration record.
  46.      * @return the system configuration record
  47.      */
  48.     public SystemConfiguration getSystemRecord() {
  49.         return systemConfigurationRecords.isEmpty() ? null : systemConfigurationRecords.get(0);
  50.     }

  51.     /**
  52.      * Get the system configuration record.
  53.      * @return the system configuration record
  54.      */
  55.     public SystemConfiguration getLastSystemRecord() {
  56.         return systemConfigurationRecords.isEmpty() ? null : systemConfigurationRecords.get(systemConfigurationRecords.size() - 1);
  57.     }

  58.     /**
  59.      * Get the laser configuration record.
  60.      * @return the laser configuration record
  61.      */
  62.     public LaserConfiguration getLaserRecord() {
  63.         return getLaserRecord(getSystemRecord());
  64.     }

  65.     /**
  66.      * Get the detector configuration record.
  67.      * @return the detector configuration record
  68.      */
  69.     public DetectorConfiguration getDetectorRecord() {
  70.         return getDetectorRecord(getSystemRecord());
  71.     }

  72.     /**
  73.      * Get the timing system configuration record.
  74.      * @return the timing system configuration record
  75.      */
  76.     public TimingSystemConfiguration getTimingRecord() {
  77.         return getTimingRecord(getSystemRecord());
  78.     }

  79.     /**
  80.      * Get the transponder configuration record.
  81.      * @return the transponder configuration record
  82.      */
  83.     public TransponderConfiguration getTransponderRecord() {
  84.         return getTransponderRecord(getSystemRecord());
  85.     }


  86.     /**
  87.      * Get the software configuration record.
  88.      * @return the software configuration record
  89.      */
  90.     public SoftwareConfiguration getSoftwareRecord() {
  91.         return getSoftwareRecord(getSystemRecord());
  92.     }

  93.     /**
  94.      * Get the meteorological record.
  95.      * @return the meteorological record
  96.      */
  97.     public MeteorologicalConfiguration getMeteorologicalRecord() {
  98.         return getMeteorologicalRecord(getSystemRecord());
  99.     }

  100.     /**
  101.      * Add a configuration record, such as SystemConfiguation, LaserConfiguration, DetectorConfiguration, etc.
  102.      * @param config the configuration record
  103.      * @since 12.0
  104.      */
  105.     public void addConfigurationRecord(final BaseConfiguration config) {
  106.         if (config == null) {
  107.             return;
  108.         }

  109.         mapConfigurationRecords.put(config.getConfigurationId(), config);

  110.         if (config instanceof SystemConfiguration) {
  111.             // Add to the list systemConfigurationRecords if it is a SystemConfiguration
  112.             systemConfigurationRecords.add((SystemConfiguration) config);
  113.         }
  114.     }

  115.     /**
  116.      * Get the configuration records map.
  117.      * @return the configuration records map
  118.      * @since 12.0
  119.      */
  120.     public Map<String, BaseConfiguration> getConfigurationRecordMap() {
  121.         return Collections.unmodifiableMap(mapConfigurationRecords);
  122.     }

  123.     /**
  124.      * Get configuration record corresponding to the configId.
  125.      * @param configId the id of configuration
  126.      * @return the configuration with configId, or null
  127.      * @since 12.0
  128.      */
  129.     public BaseConfiguration getConfigurationRecord(final String configId) {
  130.         return mapConfigurationRecords.get(configId);
  131.     }

  132.     /**
  133.      * Get a set of configuration ids.
  134.      * @return an unmodifiable set of configuration ids
  135.      * @since 12.0
  136.      */
  137.     public Set<String> getSystemConfigurationIds() {
  138.         return Collections.unmodifiableSet(mapConfigurationRecords.keySet());
  139.     }

  140.     /**
  141.      * Get a list of system configurations.
  142.      * @return an unmodifiable list of system configurations
  143.      * @since 12.0
  144.      */
  145.     public List<SystemConfiguration> getSystemConfigurationRecords() {
  146.         return Collections.unmodifiableList(systemConfigurationRecords);
  147.     }

  148.     /**
  149.      * Get configuration record related to systemRecord and the given class.
  150.      * @param systemRecord system configuration record
  151.      * @param c the class, such as LaserConfiguration, DetectorConfiguration, TimingSystemConfiguration, etc
  152.      * @return the configuration record
  153.      * @since 12.0
  154.      */
  155.     private BaseConfiguration getRecord(final SystemConfiguration systemRecord,
  156.             final Class<? extends BaseConfiguration> c) {
  157.         BaseConfiguration config;
  158.         for (final String configId : systemRecord.getComponents()) {
  159.             config = getConfigurationRecord(configId);
  160.             if (config != null && config.getClass() == c) {
  161.                 return config;
  162.             }
  163.         }

  164.         return null;
  165.     }

  166.     /**
  167.      * Get system configuration record. If configId is null, the default(first system configuration record) is returned.
  168.      * @param configId system configuration id, it can be null.
  169.      * @return the system configuration record
  170.      * @since 12.0
  171.      */
  172.     public SystemConfiguration getSystemRecord(final String configId) {
  173.         if (configId == null) {
  174.             // default
  175.             return getSystemRecord();
  176.         }

  177.         final BaseConfiguration config = mapConfigurationRecords.get(configId);
  178.         return config == null ? null : (SystemConfiguration) config;
  179.     }

  180.     /**
  181.      * Get laser configuration record related to the systemRecord.
  182.      * @param systemRecord the system configuration
  183.      * @return the laser configuration record related the the systemRecord
  184.      * @since 12.0
  185.      */
  186.     public LaserConfiguration getLaserRecord(final SystemConfiguration systemRecord) {
  187.         final BaseConfiguration config = getRecord(systemRecord, LaserConfiguration.class);
  188.         return config == null ? null : (LaserConfiguration) config;
  189.     }

  190.     /**
  191.      * Get detector configuration record related to the systemRecord.
  192.      * @param systemRecord the system configuration
  193.      * @return the detector configuration record related the the systemRecord
  194.      * @since 12.0
  195.      */
  196.     public DetectorConfiguration getDetectorRecord(final SystemConfiguration systemRecord) {
  197.         final BaseConfiguration config = getRecord(systemRecord, DetectorConfiguration.class);
  198.         return config == null ? null : (DetectorConfiguration) config;
  199.     }

  200.     /**
  201.      * Get timing system configuration record related to the systemRecord.
  202.      * @param systemRecord the system configuration
  203.      * @return the timing system configuration record related the the systemRecord
  204.      * @since 12.0
  205.      */
  206.     public TimingSystemConfiguration getTimingRecord(final SystemConfiguration systemRecord) {
  207.         final BaseConfiguration config = getRecord(systemRecord, TimingSystemConfiguration.class);
  208.         return config == null ? null : (TimingSystemConfiguration) config;
  209.     }

  210.     /**
  211.      * Get transponder configuration record related to the systemRecord.
  212.      * @param systemRecord the system configuration
  213.      * @return the transponder configuration record related the the systemRecord
  214.      * @since 12.0
  215.      */
  216.     public TransponderConfiguration getTransponderRecord(final SystemConfiguration systemRecord) {
  217.         final BaseConfiguration config = getRecord(systemRecord, TransponderConfiguration.class);
  218.         return config == null ? null : (TransponderConfiguration) config;
  219.     }

  220.     /**
  221.      * Get software configuration record related to the systemRecord.
  222.      * @param systemRecord the system configuration
  223.      * @return the software configuration record related the the systemRecord
  224.      * @since 12.0
  225.      */
  226.     public SoftwareConfiguration getSoftwareRecord(final SystemConfiguration systemRecord) {
  227.         final BaseConfiguration config = getRecord(systemRecord, SoftwareConfiguration.class);
  228.         return config == null ? null : (SoftwareConfiguration) config;
  229.     }

  230.     /**
  231.      * Get meteorological configuration record related to the systemRecord.
  232.      * @param systemRecord the system configuration
  233.      * @return the meteorological configuration record related the the systemRecord
  234.      * @since 12.0
  235.      */
  236.     public MeteorologicalConfiguration getMeteorologicalRecord(final SystemConfiguration systemRecord) {
  237.         final BaseConfiguration config = getRecord(systemRecord, MeteorologicalConfiguration.class);
  238.         return config == null ? null : (MeteorologicalConfiguration) config;
  239.     }

  240.     /**
  241.      * Get calibration target configuration record related to the systemRecord.
  242.      * @param systemRecord the system configuration
  243.      * @return the calibration target configuration record related the the systemRecord
  244.      * @since 12.0
  245.      */
  246.     public CalibrationTargetConfiguration getCalibrationTargetRecord(final SystemConfiguration systemRecord) {
  247.         final BaseConfiguration config = getRecord(systemRecord, CalibrationTargetConfiguration.class);
  248.         return config == null ? null : (CalibrationTargetConfiguration) config;
  249.     }

  250.     /**
  251.      * Get the calibration target configuration record.
  252.      * @return the calibration target configuration record
  253.      * @since 12.0
  254.      */
  255.     public CalibrationTargetConfiguration getCalibrationTargetRecord() {
  256.         return getCalibrationTargetRecord(getSystemRecord());
  257.     }

  258.     /**
  259.      * Base class for configuration record.
  260.      * @since 12.0
  261.      */
  262.     public abstract static class BaseConfiguration {

  263.         /** Configuration ID. */
  264.         private String configurationId;

  265.         /** Empty constructor.
  266.          * <p>
  267.          * This constructor is not strictly necessary, but it prevents spurious
  268.          * javadoc warnings with JDK 18 and later.
  269.          * </p>
  270.          * @since 12.0
  271.          */
  272.         public BaseConfiguration() {
  273.             // nothing to do
  274.         }

  275.         /**
  276.          * Get the configuration ID.
  277.          * @return the configuration ID
  278.          */
  279.         public String getConfigurationId() {
  280.             return configurationId;
  281.         }

  282.         /**
  283.          * Set the configuration ID.
  284.          * @param configurationId the configuration ID to set
  285.          */
  286.         public void setConfigurationId(final String configurationId) {
  287.             this.configurationId = configurationId;
  288.         }

  289.         @Override
  290.         public int hashCode() {
  291.             return toString().hashCode();
  292.         }

  293.         @Override
  294.         public boolean equals(final Object record) {
  295.             if (record == null) {
  296.                 return false;
  297.             }

  298.             if (record == this) {
  299.                 return true;
  300.             }

  301.             return toString().equals(record.toString());

  302.         }

  303.         /**
  304.          * Get a string representation of the instance in the CRD format.
  305.          * @return a string representation of the instance, in the CRD format.
  306.          * @since 12.0
  307.          */
  308.         public abstract String toCrdString();
  309.     }

  310.     /** Container for system configuration record. */
  311.     public static class SystemConfiguration extends BaseConfiguration {

  312.         /** Transmit Wavelength [m]. */
  313.         private double wavelength;

  314.         /** List of components. **/
  315.         private List<String> components;

  316.         /**
  317.          * Constructor.
  318.          */
  319.         public SystemConfiguration() {
  320.             this.components = new ArrayList<>();
  321.         }

  322.         /**
  323.          * Get the transmit wavelength.
  324.          * @return the transmit wavelength in meters
  325.          */
  326.         public double getWavelength() {
  327.             return wavelength;
  328.         }

  329.         /**
  330.          * Set the transmit wavelength.
  331.          * @param wavelength the wavelength to set
  332.          */
  333.         public void setWavelength(final double wavelength) {
  334.             this.wavelength = wavelength;
  335.         }

  336.         /**
  337.          * Get the system configuration ID.
  338.          * @return the system configuration ID
  339.          */
  340.         public String getSystemId() {
  341.             return getConfigurationId();
  342.         }

  343.         /**
  344.          * Set the system configuration ID.
  345.          * @param systemId the system configuration ID to set
  346.          */
  347.         public void setSystemId(final String systemId) {
  348.             setConfigurationId(systemId);
  349.         }

  350.         /**
  351.          * Get the components (config ids) for system configuration.
  352.          * @return an unmodifiable list of components
  353.          * @since 12.0
  354.          */
  355.         public List<String> getComponents() {
  356.             return Collections.unmodifiableList(components);
  357.         }

  358.         /**
  359.          * Set the components (config ids) for system configuration.
  360.          * @param components the components (config ids)
  361.          * @since 12.0
  362.          */
  363.         public void setComponents(final String[] components) {
  364.             this.components = Arrays.asList(components);
  365.         }

  366.         /** {@inheritDoc} */
  367.         @Override
  368.         public String toCrdString() {
  369.             return String.format("C0 0 %s", toString());
  370.         }

  371.         @Override
  372.         public String toString() {
  373.             // CRD suggested format, excluding the record type
  374.             final StringBuilder sb = new StringBuilder();
  375.             sb.append(String.format("%10.3f %s", wavelength * 1e9, getConfigurationId()));
  376.             for (final String comp : components) {
  377.                 sb.append(String.format(" %s", comp));
  378.             }
  379.             return sb.toString().replace(',', '.');
  380.         }
  381.     }

  382.     /** Container for laser configuration record. */
  383.     public static class LaserConfiguration extends BaseConfiguration {

  384.         /** Laser Type. */
  385.         private String laserType;

  386.         /** Primary wavelength [m]. */
  387.         private double primaryWavelength;

  388.         /** Nominal Fire Rate [Hz]. */
  389.         private double nominalFireRate;

  390.         /** Pulse Energy [mJ]. */
  391.         private double pulseEnergy;

  392.         /** Pulse Width [ps]. */
  393.         private double pulseWidth;

  394.         /** Bean divergence [arcsec]. */
  395.         private double beamDivergence;

  396.         /** Number of pulses in outgoing semi-train. */
  397.         private int pulseInOutgoingSemiTrain;

  398.         /** Empty constructor.
  399.          * <p>
  400.          * This constructor is not strictly necessary, but it prevents spurious
  401.          * javadoc warnings with JDK 18 and later.
  402.          * </p>
  403.          * @since 12.0
  404.          */
  405.         public LaserConfiguration() {
  406.             // nothing to do
  407.         }

  408.         /**
  409.          * Get the laser configuration ID.
  410.          * @return the laser configuration ID
  411.          */
  412.         public String getLaserId() {
  413.             return getConfigurationId();
  414.         }

  415.         /**
  416.          * Set the laser configuration ID.
  417.          * @param laserId the laser configuration ID to set
  418.          */
  419.         public void setLaserId(final String laserId) {
  420.             setConfigurationId(laserId);
  421.         }

  422.         /**
  423.          * Get the laser type.
  424.          * @return the laser type
  425.          */
  426.         public String getLaserType() {
  427.             return laserType;
  428.         }

  429.         /**
  430.          * Set the laser type.
  431.          * @param laserType the laser type to set
  432.          */
  433.         public void setLaserType(final String laserType) {
  434.             this.laserType = laserType;
  435.         }

  436.         /**
  437.          * Get the primary wavelength.
  438.          * @return the primary wavelength in meters
  439.          */
  440.         public double getPrimaryWavelength() {
  441.             return primaryWavelength;
  442.         }

  443.         /**
  444.          * Set the primary wavelength.
  445.          * @param primaryWavelength the primary wavelength to set in meters
  446.          */
  447.         public void setPrimaryWavelength(final double primaryWavelength) {
  448.             this.primaryWavelength = primaryWavelength;
  449.         }

  450.         /**
  451.          * Get the nominal fire rate.
  452.          * @return the nominal fire rate in Hz.
  453.          */
  454.         public double getNominalFireRate() {
  455.             return nominalFireRate;
  456.         }

  457.         /**
  458.          * Set the nominal fire rate.
  459.          * @param nominalFireRate the nominal fire rate to set in Hz
  460.          */
  461.         public void setNominalFireRate(final double nominalFireRate) {
  462.             this.nominalFireRate = nominalFireRate;
  463.         }

  464.         /**
  465.          * Get the pulse energy.
  466.          * @return the pulse energy in mJ
  467.          */
  468.         public double getPulseEnergy() {
  469.             return pulseEnergy;
  470.         }

  471.         /**
  472.          * Set the pulse energy.
  473.          * @param pulseEnergy the pulse energy to set in mJ
  474.          */
  475.         public void setPulseEnergy(final double pulseEnergy) {
  476.             this.pulseEnergy = pulseEnergy;
  477.         }

  478.         /**
  479.          * Get the pulse width (FWHM in ps).
  480.          * @return the pulse width
  481.          */
  482.         public double getPulseWidth() {
  483.             return pulseWidth;
  484.         }

  485.         /**
  486.          * Set the pulse width.
  487.          * @param pulseWidth the pulse width to set, ps
  488.          */
  489.         public void setPulseWidth(final double pulseWidth) {
  490.             this.pulseWidth = pulseWidth;
  491.         }

  492.         /**
  493.          * Get the beam divergence.
  494.          * @return the beam divergence in arcsec
  495.          */
  496.         public double getBeamDivergence() {
  497.             return beamDivergence;
  498.         }

  499.         /**
  500.          * Set the beam divergence.
  501.          * @param beamDivergence the beam divergence to set in arcsec
  502.          */
  503.         public void setBeamDivergence(final double beamDivergence) {
  504.             this.beamDivergence = beamDivergence;
  505.         }

  506.         /**
  507.          * Get the number of pulses in outgoing semi-train.
  508.          * @return the number of pulses in outgoing semi-train
  509.          */
  510.         public int getPulseInOutgoingSemiTrain() {
  511.             return pulseInOutgoingSemiTrain;
  512.         }

  513.         /**
  514.          * Set the number of pulses in outgoing semi-train.
  515.          * @param pulseInOutgoingSemiTrain the number of pulses in outgoing semi-train to set
  516.          */
  517.         public void setPulseInOutgoingSemiTrain(final int pulseInOutgoingSemiTrain) {
  518.             this.pulseInOutgoingSemiTrain = pulseInOutgoingSemiTrain;
  519.         }

  520.         /** {@inheritDoc} */
  521.         @Override
  522.         public String toCrdString() {
  523.             return String.format("C1 0 %s", toString());
  524.         }

  525.         @Override
  526.         public String toString() {
  527.             // CRD suggested format, excluding the record type
  528.             // primaryWavelength: m --> nm
  529.             final String str = String.format(
  530.                     "%s %s %.2f %.2f %.2f %.1f %.2f %d", getConfigurationId(),
  531.                     laserType, primaryWavelength * 1e9, nominalFireRate,
  532.                     pulseEnergy, pulseWidth, beamDivergence,
  533.                     pulseInOutgoingSemiTrain);
  534.             return CRD.handleNaN(str).replace(',', '.');
  535.         }

  536.     }

  537.     /** Container for detector configuration record. */
  538.     public static class DetectorConfiguration extends BaseConfiguration {

  539.         /** Detector Type. */
  540.         private String detectorType;

  541.         /** Applicable wavelength. */
  542.         private double applicableWavelength;

  543.         /** Quantum efficiency at applicable wavelength [%]. */
  544.         private double quantumEfficiency;

  545.         /** Applied voltage [V]. */
  546.         private double appliedVoltage;

  547.         /** Dark Count [Hz]. */
  548.         private double darkCount;

  549.         /** Output pulse type. */
  550.         private String outputPulseType;

  551.         /** Output pulse width [ps]. */
  552.         private double outputPulseWidth;

  553.         /** Spectral Filter [m]. */
  554.         private double spectralFilter;

  555.         /** % Transmission of Spectral Filter. */
  556.         private double transmissionOfSpectralFilter;

  557.         /** Spatial Filter [arcsec]. */
  558.         private double spatialFilter;

  559.         /** External Signal processing. */
  560.         private String externalSignalProcessing;

  561.         /** Amplifier Gain. */
  562.         private double amplifierGain;

  563.         /** Amplifier Bandwidth [Hz]. */
  564.         private double amplifierBandwidth;

  565.         /** Amplifier In Use. */
  566.         private String amplifierInUse;

  567.         /** Empty constructor.
  568.          * <p>
  569.          * This constructor is not strictly necessary, but it prevents spurious
  570.          * javadoc warnings with JDK 18 and later.
  571.          * </p>
  572.          * @since 12.0
  573.          */
  574.         public DetectorConfiguration() {
  575.             // nothing to do
  576.         }

  577.         /**
  578.          * Get the detector configuration ID.
  579.          * @return the detector configuration ID
  580.          */
  581.         public String getDetectorId() {
  582.             return getConfigurationId();
  583.         }

  584.         /**
  585.          * Set the detector configuration ID.
  586.          * @param detectorId the detector configuration ID to set
  587.          */
  588.         public void setDetectorId(final String detectorId) {
  589.             setConfigurationId(detectorId);
  590.         }

  591.         /**
  592.          * Get the detector type.
  593.          * @return the detector type
  594.          */
  595.         public String getDetectorType() {
  596.             return detectorType;
  597.         }

  598.         /**
  599.          * Set the detector type.
  600.          * @param detectorType the detector type to set
  601.          */
  602.         public void setDetectorType(final String detectorType) {
  603.             this.detectorType = detectorType;
  604.         }

  605.         /**
  606.          * Get the applicable wavelength.
  607.          * @return pplicable wavelength in meters
  608.          */
  609.         public double getApplicableWavelength() {
  610.             return applicableWavelength;
  611.         }

  612.         /**
  613.          * Set the applicable wavelength.
  614.          * @param applicableWavelength the applicable wavelength to set in meters
  615.          */
  616.         public void setApplicableWavelength(final double applicableWavelength) {
  617.             this.applicableWavelength = applicableWavelength;
  618.         }

  619.         /**
  620.          * Get the quantum efficiency at applicable wavelength.
  621.          * @return the quantum efficiency at applicable wavelength in percents
  622.          */
  623.         public double getQuantumEfficiency() {
  624.             return quantumEfficiency;
  625.         }

  626.         /**
  627.          * Set the quantum efficiency at applicable wavelength.
  628.          * @param quantumEfficiency the efficiency to set in percents
  629.          */
  630.         public void setQuantumEfficiency(final double quantumEfficiency) {
  631.             // NOTE: The quantumEfficiency may be -1.0, which means 'not available'
  632.             if (quantumEfficiency == -1.0) {
  633.                 this.quantumEfficiency = Double.NaN;
  634.             } else {
  635.                 this.quantumEfficiency = quantumEfficiency;
  636.             }
  637.         }

  638.         /**
  639.          * Get the applied voltage.
  640.          * @return the applied voltage in Volts
  641.          */
  642.         public double getAppliedVoltage() {
  643.             return appliedVoltage;
  644.         }

  645.         /**
  646.          * Set the applied voltage.
  647.          * @param appliedVoltage the applied voltage to set in Volts
  648.          */
  649.         public void setAppliedVoltage(final double appliedVoltage) {
  650.             // NOTE: The quantumEfficiency may be -1.0, which means 'not available' or 'not applicable'
  651.             if (appliedVoltage == -1.0) {
  652.                 this.appliedVoltage = Double.NaN;
  653.             } else {
  654.                 this.appliedVoltage = appliedVoltage;
  655.             }
  656.         }

  657.         /**
  658.          * Get the dark count.
  659.          * @return the dark count in Hz
  660.          */
  661.         public double getDarkCount() {
  662.             return darkCount;
  663.         }

  664.         /**
  665.          * Set the dark count.
  666.          * @param darkCount the dark count to set in Hz
  667.          */
  668.         public void setDarkCount(final double darkCount) {
  669.          // NOTE: The quantumEfficiency may be -1.0, which means 'not available'
  670.             if (darkCount == -1.0e3) { // -1=na, kHz --> Hz
  671.                 this.darkCount = Double.NaN;
  672.             } else {
  673.                 this.darkCount = darkCount;
  674.             }
  675.         }

  676.         /**
  677.          * Get the output pulse type.
  678.          * @return the output pulse type
  679.          */
  680.         public String getOutputPulseType() {
  681.             return outputPulseType;
  682.         }

  683.         /**
  684.          * Set the output pulse type.
  685.          * @param outputPulseType the output pulse type to set
  686.          */
  687.         public void setOutputPulseType(final String outputPulseType) {
  688.             this.outputPulseType = outputPulseType;
  689.         }

  690.         /**
  691.          * Get the output pulse width.
  692.          * @return the output pulse width in ps
  693.          */
  694.         public double getOutputPulseWidth() {
  695.             return outputPulseWidth;
  696.         }

  697.         /**
  698.          * Set the output pulse width.
  699.          * @param outputPulseWidth the output pulse width to set in ps
  700.          */
  701.         public void setOutputPulseWidth(final double outputPulseWidth) {
  702.             // NOTE: The quantumEfficiency may be -1.0, which means 'not available' or 'not applicable'
  703.             if (outputPulseWidth == -1.0) {
  704.                 this.outputPulseWidth = Double.NaN;
  705.             } else {
  706.                 this.outputPulseWidth = outputPulseWidth;
  707.             }
  708.         }

  709.         /**
  710.          * Get the spectral filter.
  711.          * @return the spectral filter in meters
  712.          */
  713.         public double getSpectralFilter() {
  714.             return spectralFilter;
  715.         }

  716.         /**
  717.          * Set the spectral filter.
  718.          * @param spectralFilter  the spectral filter to set in meters
  719.          */
  720.         public void setSpectralFilter(final double spectralFilter) {
  721.             this.spectralFilter = spectralFilter;
  722.         }

  723.         /**
  724.          * Get the percentage of transmission of spectral filter.
  725.          * @return the percentage of transmission of spectral filter
  726.          */
  727.         public double getTransmissionOfSpectralFilter() {
  728.             return transmissionOfSpectralFilter;
  729.         }

  730.         /**
  731.          * Set the percentage of transmission of spectral filter.
  732.          * @param transmissionOfSpectralFilter the percentage to set
  733.          */
  734.         public void setTransmissionOfSpectralFilter(final double transmissionOfSpectralFilter) {
  735.             this.transmissionOfSpectralFilter = transmissionOfSpectralFilter;
  736.         }

  737.         /**
  738.          * Get the spatial filter.
  739.          * @return the spatial filter in arcsec
  740.          */
  741.         public double getSpatialFilter() {
  742.             return spatialFilter;
  743.         }

  744.         /**
  745.          * Set the spatial filter.
  746.          * @param spatialFilter the spatial filter to set in arcsec
  747.          */
  748.         public void setSpatialFilter(final double spatialFilter) {
  749.             this.spatialFilter = spatialFilter;
  750.         }

  751.         /**
  752.          * Get the external signal processing.
  753.          * @return the external signal processing
  754.          */
  755.         public String getExternalSignalProcessing() {
  756.             return externalSignalProcessing;
  757.         }

  758.         /**
  759.          * Set the external signal processing.
  760.          * @param externalSignalProcessing the external signal processing to set
  761.          */
  762.         public void setExternalSignalProcessing(final String externalSignalProcessing) {
  763.             this.externalSignalProcessing = externalSignalProcessing;
  764.         }

  765.         /**
  766.          * Get the amplifier gain.
  767.          * @return the amplifier gain
  768.          */
  769.         public double getAmplifierGain() {
  770.             return amplifierGain;
  771.         }

  772.         /**
  773.          * Set the amplifier gain.
  774.          * @param amplifierGain the amplifier gain to set
  775.          */
  776.         public void setAmplifierGain(final double amplifierGain) {
  777.             this.amplifierGain = amplifierGain;
  778.         }

  779.         /**
  780.          * Get the amplifier bandwidth.
  781.          * @return the amplifier bandwidth in Hz
  782.          */
  783.         public double getAmplifierBandwidth() {
  784.             return amplifierBandwidth;
  785.         }

  786.         /**
  787.          * Set the amplifier bandwidth.
  788.          * @param amplifierBandwidth the amplifier bandwidth to set in Hz
  789.          */
  790.         public void setAmplifierBandwidth(final double amplifierBandwidth) {
  791.             this.amplifierBandwidth = amplifierBandwidth;
  792.         }

  793.         /**
  794.          * Get the amplifier in use.
  795.          * @return the amplifier in use
  796.          */
  797.         public String getAmplifierInUse() {
  798.             return amplifierInUse;
  799.         }

  800.         /**
  801.          * Set the amplifier in use.
  802.          * @param amplifierInUse the amplifier in use to set
  803.          */
  804.         public void setAmplifierInUse(final String amplifierInUse) {
  805.             this.amplifierInUse = amplifierInUse;
  806.         }

  807.         /** {@inheritDoc} */
  808.         @Override
  809.         public String toCrdString() {
  810.             return String.format("C2 0 %s", toString());
  811.         }

  812.         @Override
  813.         public String toString() {
  814.             // CRD suggested format, excluding the record type
  815.             // applicableWavelength, spectralFilter: m --> nm
  816.             // darkCount, amplifierBandwidth: Hz --> kHz
  817.             final String str = String.format(
  818.                     "%s %s %.3f %.2f %.1f %.1f %s %.1f %.2f %.1f %.1f %s %.1f %.1f %s",
  819.                     getConfigurationId(), detectorType,
  820.                     applicableWavelength * 1e9, quantumEfficiency,
  821.                     appliedVoltage, darkCount * 1e-3, outputPulseType,
  822.                     outputPulseWidth, spectralFilter * 1e9,
  823.                     transmissionOfSpectralFilter, spatialFilter,
  824.                     externalSignalProcessing, amplifierGain,
  825.                     amplifierBandwidth * 1e-3, amplifierInUse);
  826.             return CRD.handleNaN(str).replace(',', '.');
  827.         }
  828.     }

  829.     /** Container for timing system configuration record. */
  830.     public static class TimingSystemConfiguration extends BaseConfiguration {

  831.         /** Time Source. */
  832.         private String timeSource;

  833.         /** Frequency Source. */
  834.         private String frequencySource;

  835.         /** Timer. */
  836.         private String timer;

  837.         /** Timer Serial Number. */
  838.         private String timerSerialNumber;

  839.         /** Epoch delay correction [s]. */
  840.         private double epochDelayCorrection;

  841.         /** Empty constructor.
  842.          * <p>
  843.          * This constructor is not strictly necessary, but it prevents spurious
  844.          * javadoc warnings with JDK 18 and later.
  845.          * </p>
  846.          * @since 12.0
  847.          */
  848.         public TimingSystemConfiguration() {
  849.             // nothing to do
  850.         }

  851.         /**
  852.          * Get the time source.
  853.          * @return the time source
  854.          */
  855.         public String getTimeSource() {
  856.             return timeSource;
  857.         }

  858.         /**
  859.          * Get the local timing system configuration ID.
  860.          * @return the local timing system configuration ID
  861.          */
  862.         public String getLocalTimingId() {
  863.             return getConfigurationId();
  864.         }

  865.         /**
  866.          * Set the local timing system configuration ID.
  867.          * @param localTimingId the local timing system configuration ID to set
  868.          */
  869.         public void setLocalTimingId(final String localTimingId) {
  870.             setConfigurationId(localTimingId);
  871.         }

  872.         /**
  873.          * Set the time source.
  874.          * @param timeSource the time source to set
  875.          */
  876.         public void setTimeSource(final String timeSource) {
  877.             this.timeSource = timeSource;
  878.         }

  879.         /**
  880.          * Get the frequency source.
  881.          * @return the frequency source
  882.          */
  883.         public String getFrequencySource() {
  884.             return frequencySource;
  885.         }

  886.         /**
  887.          * Set the frequency source.
  888.          * @param frequencySource the frequency source to set
  889.          */
  890.         public void setFrequencySource(final String frequencySource) {
  891.             this.frequencySource = frequencySource;
  892.         }

  893.         /**
  894.          * Get the timer name.
  895.          * @return the timer name
  896.          */
  897.         public String getTimer() {
  898.             return timer;
  899.         }

  900.         /**
  901.          * Set the timer name.
  902.          * @param timer the timer name to set
  903.          */
  904.         public void setTimer(final String timer) {
  905.             this.timer = timer;
  906.         }

  907.         /**
  908.          * Get the timer serial number.
  909.          * @return the timer serial number
  910.          */
  911.         public String getTimerSerialNumber() {
  912.             return timerSerialNumber;
  913.         }

  914.         /**
  915.          * Set the timer serial number.
  916.          * @param timerSerialNumber the timer serial number to set
  917.          */
  918.         public void setTimerSerialNumber(final String timerSerialNumber) {
  919.             this.timerSerialNumber = timerSerialNumber;
  920.         }

  921.         /**
  922.          * Get the epoch delay correction.
  923.          * @return the epoch delay correction in seconds
  924.          */
  925.         public double getEpochDelayCorrection() {
  926.             return epochDelayCorrection;
  927.         }

  928.         /**
  929.          * Set the epoch delay correction.
  930.          * @param epochDelayCorrection the epoch delay correction to set in seconds
  931.          */
  932.         public void setEpochDelayCorrection(final double epochDelayCorrection) {
  933.             this.epochDelayCorrection = epochDelayCorrection;
  934.         }

  935.         /** {@inheritDoc} */
  936.         @Override
  937.         public String toCrdString() {
  938.             return String.format("C3 0 %s", toString());
  939.         }

  940.         @Override
  941.         public String toString() {
  942.             // CRD suggested format, excluding the record type
  943.             // epochDelayCorrection: s --> us
  944.             final String str = String.format("%s %s %s %s %s %.1f",
  945.                     getConfigurationId(), timeSource, frequencySource, timer,
  946.                     timerSerialNumber, epochDelayCorrection * 1e6);
  947.             return CRD.handleNaN(str).replace(',', '.');
  948.         }
  949.     }

  950.     /** Container for transponder configuration record. */
  951.     public static class TransponderConfiguration extends BaseConfiguration {

  952.         /** Estimated Station UTC offset [s]. */
  953.         private double stationUTCOffset;

  954.         /** Estimated Station Oscillator Drift in parts in 10^15. */
  955.         private double stationOscDrift;

  956.         /** Estimated Transponder UTC offset [s]. */
  957.         private double transpUTCOffset;

  958.         /** Estimated Transponder Oscillator Drift in parts in 10^15. */
  959.         private double transpOscDrift;

  960.         /** Transponder Clock Reference Time. */
  961.         private double transpClkRefTime;

  962.         /** Station clock offset and drift applied indicator. */
  963.         private int stationClockAndDriftApplied;

  964.         /** Spacecraft clock offset and drift applied indicator . */
  965.         private int spacecraftClockAndDriftApplied;

  966.         /** Spacecraft time simplified flag. */
  967.         private boolean isSpacecraftTimeSimplified;

  968.         /** Empty constructor.
  969.          * <p>
  970.          * This constructor is not strictly necessary, but it prevents spurious
  971.          * javadoc warnings with JDK 18 and later.
  972.          * </p>
  973.          * @since 12.0
  974.          */
  975.         public TransponderConfiguration() {
  976.             // nothing to do
  977.         }

  978.         /**
  979.          * Get the transponder configuration ID.
  980.          * @return the transponder configuration ID
  981.          */
  982.         public String getTransponderId() {
  983.             return getConfigurationId();
  984.         }

  985.         /**
  986.          * Set the transponder configuration ID.
  987.          * @param transponderId the transponder configuration ID to set
  988.          */
  989.         public void setTransponderId(final String transponderId) {
  990.             setConfigurationId(transponderId);
  991.         }

  992.         /**
  993.          * Get the estimated station UTC offset.
  994.          * @return the estimated station UTC offset in seconds
  995.          */
  996.         public double getStationUTCOffset() {
  997.             return stationUTCOffset;
  998.         }

  999.         /**
  1000.          * Set the estimated station UTC offset.
  1001.          * @param stationUTCOffset the estimated station UTC offset to set in seconds
  1002.          */
  1003.         public void setStationUTCOffset(final double stationUTCOffset) {
  1004.             this.stationUTCOffset = stationUTCOffset;
  1005.         }

  1006.         /**
  1007.          * Get the estimated station oscillator drift in parts in 10¹⁵.
  1008.          * @return the station oscillator drift
  1009.          */
  1010.         public double getStationOscDrift() {
  1011.             return stationOscDrift;
  1012.         }

  1013.         /**
  1014.          * Set the estimated station oscillator drift in parts in 10¹⁵.
  1015.          * @param stationOscDrift the station oscillator drift to set
  1016.          */
  1017.         public void setStationOscDrift(final double stationOscDrift) {
  1018.             this.stationOscDrift = stationOscDrift;
  1019.         }

  1020.         /**
  1021.          * Get the estimated transponder UTC offset.
  1022.          * @return the estimated transponder UTC offset in seconds
  1023.          */
  1024.         public double getTranspUTCOffset() {
  1025.             return transpUTCOffset;
  1026.         }

  1027.         /**
  1028.          * Set the estimated transponder UTC offset.
  1029.          * @param transpUTCOffset the estimated transponder UTC offset to set in seconds
  1030.          */
  1031.         public void setTranspUTCOffset(final double transpUTCOffset) {
  1032.             this.transpUTCOffset = transpUTCOffset;
  1033.         }

  1034.         /**
  1035.          * Get the estimated transponder oscillator drift in parts in 10¹⁵.
  1036.          * @return the estimated transponder oscillator drift
  1037.          */
  1038.         public double getTranspOscDrift() {
  1039.             return transpOscDrift;
  1040.         }

  1041.         /**
  1042.          * Set the estimated transponder oscillator drift in parts in 10¹⁵.
  1043.          * @param transpOscDrift the estimated transponder oscillator drift to set
  1044.          */
  1045.         public void setTranspOscDrift(final double transpOscDrift) {
  1046.             this.transpOscDrift = transpOscDrift;
  1047.         }

  1048.         /**
  1049.          * Get the transponder clock reference time.
  1050.          * @return the transponder clock reference time
  1051.          */
  1052.         public double getTranspClkRefTime() {
  1053.             return transpClkRefTime;
  1054.         }

  1055.         /**
  1056.          * Set the transponder clock reference time.
  1057.          * @param transpClkRefTime the transponder clock reference time to set
  1058.          */
  1059.         public void setTranspClkRefTime(final double transpClkRefTime) {
  1060.             this.transpClkRefTime = transpClkRefTime;
  1061.         }

  1062.         /**
  1063.          * Get the station clock offset and drift applied indicator.
  1064.          * @return the station clock offset and drift applied indicator
  1065.          */
  1066.         public int getStationClockAndDriftApplied() {
  1067.             return stationClockAndDriftApplied;
  1068.         }

  1069.         /**
  1070.          * Set the station clock offset and drift applied indicator.
  1071.          * @param stationClockAndDriftApplied the indicator to set
  1072.          */
  1073.         public void setStationClockAndDriftApplied(final int stationClockAndDriftApplied) {
  1074.             this.stationClockAndDriftApplied = stationClockAndDriftApplied;
  1075.         }

  1076.         /**
  1077.          * Get the spacecraft clock offset and drift applied indicator.
  1078.          * @return the spacecraft clock offset and drift applied indicator
  1079.          */
  1080.         public int getSpacecraftClockAndDriftApplied() {
  1081.             return spacecraftClockAndDriftApplied;
  1082.         }

  1083.         /**
  1084.          * Set the spacecraft clock offset and drift applied indicator.
  1085.          * @param spacecraftClockAndDriftApplied the indicator to set
  1086.          */
  1087.         public void setSpacecraftClockAndDriftApplied(final int spacecraftClockAndDriftApplied) {
  1088.             this.spacecraftClockAndDriftApplied = spacecraftClockAndDriftApplied;
  1089.         }

  1090.         /**
  1091.          * Get the spacecraft time simplified flag.
  1092.          * @return true if spacecraft time is simplified
  1093.          */
  1094.         public boolean isSpacecraftTimeSimplified() {
  1095.             return isSpacecraftTimeSimplified;
  1096.         }

  1097.         /**
  1098.          * Set the spacecraft time simplified flag.
  1099.          * @param isSpacecraftTimeSimplified true if spacecraft time is simplified
  1100.          */
  1101.         public void setIsSpacecraftTimeSimplified(final boolean isSpacecraftTimeSimplified) {
  1102.             this.isSpacecraftTimeSimplified = isSpacecraftTimeSimplified;
  1103.         }

  1104.         /** {@inheritDoc} */
  1105.         @Override
  1106.         public String toCrdString() {
  1107.             return String.format("C4 0 %s", toString());
  1108.         }

  1109.         @Override
  1110.         public String toString() {
  1111.             // CRD suggested format, excluding the record type
  1112.             // stationUTCOffset, transpUTCOffset: s --> ns
  1113.             final String str = String.format(
  1114.                     "%s %.3f %.2f %.3f %.2f %.12f %d %d %d",
  1115.                     getConfigurationId(),
  1116.                     stationUTCOffset * 1e9, stationOscDrift,
  1117.                     transpUTCOffset * 1e9, transpOscDrift,
  1118.                     transpClkRefTime,
  1119.                     stationClockAndDriftApplied, spacecraftClockAndDriftApplied,
  1120.                     isSpacecraftTimeSimplified ? 1 : 0);
  1121.             return CRD.handleNaN(str).replace(',', '.');
  1122.         }

  1123.     }

  1124.     /** Container for software configuration record. */
  1125.     public static class SoftwareConfiguration extends BaseConfiguration {

  1126.         /** Pattern of "[\\s+\\[\\]]". */
  1127.         private static final Pattern PATTERN_WHITESPACE_OR_SQUAREBRACKET = Pattern.compile("[\\s+\\[\\]]");

  1128.         /** Tracking software in measurement path. */
  1129.         private String[] trackingSoftwares;

  1130.         /** Tracking software version(s). */
  1131.         private String[] trackingSoftwareVersions;

  1132.         /** Processing software in measurement path. */
  1133.         private String[] processingSoftwares;

  1134.         /** Processing software version(s). */
  1135.         private String[] processingSoftwareVersions;

  1136.         /** Empty constructor.
  1137.          * <p>
  1138.          * This constructor is not strictly necessary, but it prevents spurious
  1139.          * javadoc warnings with JDK 18 and later.
  1140.          * </p>
  1141.          * @since 12.0
  1142.          */
  1143.         public SoftwareConfiguration() {
  1144.             // nothing to do
  1145.         }

  1146.         /**
  1147.          * Get the software configuration ID.
  1148.          * @return the software configuration ID.
  1149.          */
  1150.         public String getSoftwareId() {
  1151.             return getConfigurationId();
  1152.         }

  1153.         /**
  1154.          * Set the software configuration ID.
  1155.          * @param softwareId the software configuration ID
  1156.          */
  1157.         public void setSoftwareId(final String softwareId) {
  1158.             setConfigurationId(softwareId);
  1159.         }

  1160.         /**
  1161.          * Get the tracking softwares.
  1162.          * @return the tracking softwares
  1163.          */
  1164.         public String[] getTrackingSoftwares() {
  1165.             return trackingSoftwares.clone();
  1166.         }

  1167.         /**
  1168.          * Set the tracking softwares.
  1169.          * @param trackingSoftwares the tracking softwares to set
  1170.          */
  1171.         public void setTrackingSoftwares(final String[] trackingSoftwares) {
  1172.             this.trackingSoftwares = trackingSoftwares.clone();
  1173.         }

  1174.         /**
  1175.          * Get the tracking software versions.
  1176.          * @return the tracking software versions
  1177.          */
  1178.         public String[] getTrackingSoftwareVersions() {
  1179.             return trackingSoftwareVersions.clone();
  1180.         }

  1181.         /**
  1182.          * Set the tracking software versions.
  1183.          * @param trackingSoftwareVersions the tracking software versions to set
  1184.          */
  1185.         public void setTrackingSoftwareVersions(final String[] trackingSoftwareVersions) {
  1186.             this.trackingSoftwareVersions = trackingSoftwareVersions.clone();
  1187.         }

  1188.         /**
  1189.          * Get the processing softwares.
  1190.          * @return the processing softwares
  1191.          */
  1192.         public String[] getProcessingSoftwares() {
  1193.             return processingSoftwares.clone();
  1194.         }

  1195.         /**
  1196.          * Set the processing softwares.
  1197.          * @param processingSoftwares the processing softwares to set
  1198.          */
  1199.         public void setProcessingSoftwares(final String[] processingSoftwares) {
  1200.             this.processingSoftwares = processingSoftwares.clone();
  1201.         }

  1202.         /**
  1203.          * Get the processing software versions.
  1204.          * @return the processing software versions
  1205.          */
  1206.         public String[] getProcessingSoftwareVersions() {
  1207.             return processingSoftwareVersions.clone();
  1208.         }

  1209.         /**
  1210.          * Set the processing software versions.
  1211.          * @param processingSoftwareVersions the processing software versions to set
  1212.          */
  1213.         public void setProcessingSoftwareVersions(final String[] processingSoftwareVersions) {
  1214.             this.processingSoftwareVersions = processingSoftwareVersions.clone();
  1215.         }

  1216.         private static String formatArray(final String[] arr) {
  1217.             // comma delimited
  1218.             // "[Monitor, Sattrk]" ==> "Monitor,Sattrk"
  1219.             // "[conpro, crd_cal, PoissonCRD, gnp]" ==> "conpro,crd_cal,PoissonCRD,gnp"
  1220.             final String s = Arrays.toString(arr);
  1221.             return PATTERN_WHITESPACE_OR_SQUAREBRACKET.matcher(s).replaceAll("");
  1222.         }

  1223.         /** {@inheritDoc} */
  1224.         @Override
  1225.         public String toCrdString() {
  1226.             return String.format("C5 0 %s", toString());
  1227.         }

  1228.         @Override
  1229.         public String toString() {
  1230.             // CRD suggested format, excluding the record type
  1231.             return String.format("%s %s %s %s %s", getConfigurationId(),
  1232.                     formatArray(trackingSoftwares),
  1233.                     formatArray(trackingSoftwareVersions),
  1234.                     formatArray(processingSoftwares),
  1235.                     formatArray(processingSoftwareVersions));
  1236.         }

  1237.     }

  1238.     /** Container for meteorological configuration record. */
  1239.     public static class MeteorologicalConfiguration extends BaseConfiguration {

  1240.         /** Pressure Sensor Manufacturer. */
  1241.         private String pressSensorManufacturer;

  1242.         /** Pressure Sensor Model. */
  1243.         private String pressSensorModel;

  1244.         /** Pressure Sensor Serial Number. */
  1245.         private String pressSensorSerialNumber;

  1246.         /** Temperature Sensor Manufacturer. */
  1247.         private String tempSensorManufacturer;

  1248.         /** Temperature Sensor Model. */
  1249.         private String tempSensorModel;

  1250.         /** Temperature Sensor Serial Number. */
  1251.         private String tempSensorSerialNumber;

  1252.         /** Humidity Sensor Manufacturer. */
  1253.         private String humiSensorManufacturer;

  1254.         /** Humidity Sensor Model. */
  1255.         private String humiSensorModel;

  1256.         /** Humidity Sensor Serial Number. */
  1257.         private String humiSensorSerialNumber;

  1258.         /** Empty constructor.
  1259.          * <p>
  1260.          * This constructor is not strictly necessary, but it prevents spurious
  1261.          * javadoc warnings with JDK 18 and later.
  1262.          * </p>
  1263.          * @since 12.0
  1264.          */
  1265.         public MeteorologicalConfiguration() {
  1266.             // nothing to do
  1267.         }

  1268.         /**
  1269.          * Get the meteorological configuration ID.
  1270.          * @return the meteorological configuration ID
  1271.          */
  1272.         public String getMeteorologicalId() {
  1273.             return getConfigurationId();
  1274.         }

  1275.         /**
  1276.          * Set the meteorological configuration ID.
  1277.          * @param meteorologicalId the meteorological configuration ID to set
  1278.          */
  1279.         public void setMeteorologicalId(final String meteorologicalId) {
  1280.             setConfigurationId(meteorologicalId);
  1281.         }

  1282.         /**
  1283.          * Get the pressure sensor manufacturer.
  1284.          * @return the pressure sensor manufacturer
  1285.          */
  1286.         public String getPressSensorManufacturer() {
  1287.             return pressSensorManufacturer;
  1288.         }

  1289.         /**
  1290.          * Set the pressure sensor manufacturer.
  1291.          * @param pressSensorManufacturer the manufacturer to set
  1292.          */
  1293.         public void setPressSensorManufacturer(final String pressSensorManufacturer) {
  1294.             this.pressSensorManufacturer = pressSensorManufacturer;
  1295.         }

  1296.         /**
  1297.          * Get the pressure sensor model.
  1298.          * @return the pressure sensor model
  1299.          */
  1300.         public String getPressSensorModel() {
  1301.             return pressSensorModel;
  1302.         }

  1303.         /**
  1304.          * Set the pressure sensor model.
  1305.          * @param pressSensorModel the model to set
  1306.          */
  1307.         public void setPressSensorModel(final String pressSensorModel) {
  1308.             this.pressSensorModel = pressSensorModel;
  1309.         }

  1310.         /**
  1311.          * Get the pressure sensor serial number.
  1312.          * @return the pressure sensor serial number
  1313.          */
  1314.         public String getPressSensorSerialNumber() {
  1315.             return pressSensorSerialNumber;
  1316.         }

  1317.         /**
  1318.          * Set the pressure sensor serial number.
  1319.          * @param pressSensorSerialNumber the serial number to set
  1320.          */
  1321.         public void setPressSensorSerialNumber(final String pressSensorSerialNumber) {
  1322.             this.pressSensorSerialNumber = pressSensorSerialNumber;
  1323.         }

  1324.         /**
  1325.          * Get the temperature sensor manufacturer.
  1326.          * @return the temperature sensor manufacturer
  1327.          */
  1328.         public String getTempSensorManufacturer() {
  1329.             return tempSensorManufacturer;
  1330.         }

  1331.         /**
  1332.          * Set the temperature sensor manufacturer.
  1333.          * @param tempSensorManufacturer the temperature sensor manufacturer
  1334.          */
  1335.         public void setTempSensorManufacturer(final String tempSensorManufacturer) {
  1336.             this.tempSensorManufacturer = tempSensorManufacturer;
  1337.         }

  1338.         /**
  1339.          * Get the temperature sensor model.
  1340.          * @return the temperature sensor model
  1341.          */
  1342.         public String getTempSensorModel() {
  1343.             return tempSensorModel;
  1344.         }

  1345.         /**
  1346.          * Set the temperature sensor model.
  1347.          * @param tempSensorModel the model to set
  1348.          */
  1349.         public void setTempSensorModel(final String tempSensorModel) {
  1350.             this.tempSensorModel = tempSensorModel;
  1351.         }

  1352.         /**
  1353.          * Get the temperature sensor serial number.
  1354.          * @return the temperature sensor serial number
  1355.          */
  1356.         public String getTempSensorSerialNumber() {
  1357.             return tempSensorSerialNumber;
  1358.         }

  1359.         /**
  1360.          * Set the temperature sensor serial number.
  1361.          * @param tempSensorSerialNumber the serial number to set
  1362.          */
  1363.         public void setTempSensorSerialNumber(final String tempSensorSerialNumber) {
  1364.             this.tempSensorSerialNumber = tempSensorSerialNumber;
  1365.         }

  1366.         /**
  1367.          * Get the humidity sensor manufacturer.
  1368.          * @return the humidity sensor manufacturer
  1369.          */
  1370.         public String getHumiSensorManufacturer() {
  1371.             return humiSensorManufacturer;
  1372.         }

  1373.         /**
  1374.          * Set the humidity sensor manufacturer.
  1375.          * @param humiSensorManufacturer the manufacturer to set
  1376.          */
  1377.         public void setHumiSensorManufacturer(final String humiSensorManufacturer) {
  1378.             this.humiSensorManufacturer = humiSensorManufacturer;
  1379.         }

  1380.         /**
  1381.          * Get the humidity sensor model.
  1382.          * @return the humidity sensor model
  1383.          */
  1384.         public String getHumiSensorModel() {
  1385.             return humiSensorModel;
  1386.         }

  1387.         /**
  1388.          * Set the humidity sensor model.
  1389.          * @param humiSensorModel the model to set
  1390.          */
  1391.         public void setHumiSensorModel(final String humiSensorModel) {
  1392.             this.humiSensorModel = humiSensorModel;
  1393.         }

  1394.         /**
  1395.          * Get the humidity sensor serial number.
  1396.          * @return the humidity sensor serial number
  1397.          */
  1398.         public String getHumiSensorSerialNumber() {
  1399.             return humiSensorSerialNumber;
  1400.         }

  1401.         /**
  1402.          * Set the humidity sensor serial number.
  1403.          * @param humiSensorSerialNumber the serial number to set
  1404.          */
  1405.         public void setHumiSensorSerialNumber(final String humiSensorSerialNumber) {
  1406.             this.humiSensorSerialNumber = humiSensorSerialNumber;
  1407.         }

  1408.         /** {@inheritDoc} */
  1409.         @Override
  1410.         public String toCrdString() {
  1411.             return String.format("C6 0 %s", toString());
  1412.         }

  1413.         @Override
  1414.         public String toString() {
  1415.             // CRD suggested format, excluding the record type
  1416.             return String.format("%s %s %s %s %s %s %s %s %s %s",
  1417.                     getConfigurationId(), pressSensorManufacturer,
  1418.                     pressSensorModel, pressSensorSerialNumber,
  1419.                     tempSensorManufacturer, tempSensorModel,
  1420.                     tempSensorSerialNumber, humiSensorManufacturer,
  1421.                     humiSensorModel, humiSensorSerialNumber);
  1422.         }
  1423.     }

  1424.     /**
  1425.      * Container for calibration target configuration record.
  1426.      * @since 12.0
  1427.      */
  1428.     public static class CalibrationTargetConfiguration extends BaseConfiguration {

  1429.         /** Target name or ID. */
  1430.         private String targetName;

  1431.         /** Surveyed target distance. */
  1432.         private double surveyedTargetDistance;

  1433.         /** Survey error. */
  1434.         private double surveyError;

  1435.         /** Sum of all constant delays (m, one way). */
  1436.         private double sumOfAllConstantDelays;

  1437.         /** Pulse Energy [mJ]. */
  1438.         private double pulseEnergy;

  1439.         /** Processing software name. */
  1440.         private String processingSoftwareName;

  1441.         /** Processing software version. */
  1442.         private String processingSoftwareVersion;

  1443.         /** Empty constructor.
  1444.          * <p>
  1445.          * This constructor is not strictly necessary, but it prevents spurious
  1446.          * javadoc warnings with JDK 18 and later.
  1447.          * </p>
  1448.          * @since 12.0
  1449.          */
  1450.         public CalibrationTargetConfiguration() {
  1451.             // nothing to do
  1452.         }

  1453.         /**
  1454.          * Get the target name or ID.
  1455.          * @return the target name or ID
  1456.          */
  1457.         public String getTargetName() {
  1458.             return targetName;
  1459.         }

  1460.         /**
  1461.          * Set the target name or ID.
  1462.          * @param targetName target name or ID to set
  1463.          */
  1464.         public void setTargetName(final String targetName) {
  1465.             this.targetName = targetName;
  1466.         }

  1467.         /**
  1468.          * Get the surveyed target distance.
  1469.          * @return the surveyed target distance in meters
  1470.          */
  1471.         public double getSurveyedTargetDistance() {
  1472.             return surveyedTargetDistance;
  1473.         }

  1474.         /**
  1475.          * Set the surveyed target distance.
  1476.          * @param surveyedTargetDistance the surveyed target distance to set, in meters
  1477.          */
  1478.         public void setSurveyedTargetDistance(final double surveyedTargetDistance) {
  1479.             this.surveyedTargetDistance = surveyedTargetDistance;
  1480.         }

  1481.         /**
  1482.          * Get the survey error.
  1483.          * @return the survey error in meters
  1484.          */
  1485.         public double getSurveyError() {
  1486.             return surveyError;
  1487.         }

  1488.         /**
  1489.          * Set the survey error.
  1490.          * @param surveyError the survey error to set, in meters
  1491.          */
  1492.         public void setSurveyError(final double surveyError) {
  1493.             this.surveyError = surveyError;
  1494.         }

  1495.         /**
  1496.          * Get the sum of all constant delays (electronic, geometric, optical) that
  1497.          * are not included in the time of flight measurements or time- variant
  1498.          * or point angle-variant delays in the “42” record below (m, one way).
  1499.          * @return the sum of all constant delays
  1500.          */
  1501.         public double getSumOfAllConstantDelays() {
  1502.             return sumOfAllConstantDelays;
  1503.         }

  1504.         /**
  1505.          * Set the sum of all constant delays (electronic, geometric, optical) that
  1506.          * are not included in the time of flight measurements or time- variant
  1507.          * or point angle-variant delays in the “42” record below (m, one way).
  1508.          * @param sumOfAllConstantDelays the sum of all constant delays
  1509.          */
  1510.         public void setSumOfAllConstantDelays(final double sumOfAllConstantDelays) {
  1511.             this.sumOfAllConstantDelays = sumOfAllConstantDelays;
  1512.         }

  1513.         /**
  1514.          * Get the pulse energy.
  1515.          * @return the pulse energy in mJ
  1516.          */
  1517.         public double getPulseEnergy() {
  1518.             return pulseEnergy;
  1519.         }

  1520.         /**
  1521.          * Set the pulse energy.
  1522.          * @param pulseEnergy the pulse energy to set, in mJ
  1523.          */
  1524.         public void setPulseEnergy(final double pulseEnergy) {
  1525.             this.pulseEnergy = pulseEnergy;
  1526.         }

  1527.         /**
  1528.          * Get the processing software name.
  1529.          * @return the processing software name
  1530.          */
  1531.         public String getProcessingSoftwareName() {
  1532.             return processingSoftwareName;
  1533.         }

  1534.         /**
  1535.          * Set the processing software name.
  1536.          * @param processingSoftwareName the processing software name to set
  1537.          */
  1538.         public void setProcessingSoftwareName(final String processingSoftwareName) {
  1539.             this.processingSoftwareName = processingSoftwareName;
  1540.         }

  1541.         /**
  1542.          * Get the processing software version.
  1543.          * @return the processing software version
  1544.          */
  1545.         public String getProcessingSoftwareVersion() {
  1546.             return processingSoftwareVersion;
  1547.         }

  1548.         /**
  1549.          * Set the processing software version.
  1550.          * @param processingSoftwareVersion the processing software version to set
  1551.          */
  1552.         public void setProcessingSoftwareVersion(final String processingSoftwareVersion) {
  1553.             this.processingSoftwareVersion = processingSoftwareVersion;
  1554.         }

  1555.         /** {@inheritDoc} */
  1556.         @Override
  1557.         public String toCrdString() {
  1558.             return String.format("C7 0 %s", toString());
  1559.         }

  1560.         @Override
  1561.         public String toString() {
  1562.             // CRD suggested format, excluding the record type
  1563.             // surveyError: m --> mm
  1564.             final String str = String.format("%s %s %.5f %.2f %.4f %.2f %s %s",
  1565.                     getConfigurationId(), targetName, surveyedTargetDistance,
  1566.                     surveyError * 1e3, sumOfAllConstantDelays, pulseEnergy,
  1567.                     processingSoftwareName, processingSoftwareVersion);
  1568.             return CRD.handleNaN(str).replace(',', '.');
  1569.         }

  1570.     }
  1571. }